From e81d9d49145e432d917eea3a70d2ae74dcad1d89 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 30 Dec 2015 11:55:28 +0000 Subject: Vendor import of stripped lldb trunk r256633: https://llvm.org/svn/llvm-project/lldb/trunk@256633 --- docs/lldb.1 | 85 +- include/lldb/API/LLDB.h | 20 + include/lldb/API/SBAttachInfo.h | 75 + include/lldb/API/SBCommandInterpreter.h | 30 +- include/lldb/API/SBCommandReturnObject.h | 20 +- include/lldb/API/SBDebugger.h | 36 +- include/lldb/API/SBDefines.h | 2 - include/lldb/API/SBFunction.h | 6 + include/lldb/API/SBProcess.h | 54 +- include/lldb/API/SBStream.h | 4 +- include/lldb/API/SBTarget.h | 70 +- include/lldb/API/SBType.h | 13 +- include/lldb/API/SBTypeCategory.h | 9 + include/lldb/API/SBTypeSummary.h | 15 +- include/lldb/API/SBValue.h | 12 +- include/lldb/API/SystemInitializerFull.h | 8 +- include/lldb/Breakpoint/Breakpoint.h | 61 +- include/lldb/Breakpoint/BreakpointLocation.h | 28 +- include/lldb/Breakpoint/BreakpointLocationList.h | 23 +- include/lldb/Breakpoint/BreakpointOptions.h | 31 +- include/lldb/Breakpoint/BreakpointResolver.h | 9 +- .../lldb/Breakpoint/BreakpointResolverAddress.h | 17 +- .../lldb/Breakpoint/BreakpointResolverFileLine.h | 5 +- .../lldb/Breakpoint/BreakpointResolverFileRegex.h | 5 +- include/lldb/Breakpoint/BreakpointResolverName.h | 11 +- include/lldb/Breakpoint/BreakpointSite.h | 25 +- include/lldb/Breakpoint/Watchpoint.h | 58 +- include/lldb/Breakpoint/WatchpointOptions.h | 27 +- include/lldb/Core/Address.h | 23 +- include/lldb/Core/AddressRange.h | 8 +- include/lldb/Core/AddressResolver.h | 9 +- include/lldb/Core/AddressResolverFileLine.h | 17 +- include/lldb/Core/AddressResolverName.h | 17 +- include/lldb/Core/ArchSpec.h | 44 +- include/lldb/Core/Broadcaster.h | 24 +- include/lldb/Core/ClangForward.h | 2 + include/lldb/Core/Communication.h | 29 +- include/lldb/Core/Connection.h | 12 +- include/lldb/Core/ConnectionSharedMemory.h | 31 +- include/lldb/Core/ConstString.h | 46 +- include/lldb/Core/DataBufferHeap.h | 19 +- include/lldb/Core/DataBufferMemoryMap.h | 20 +- include/lldb/Core/DataEncoder.h | 2 +- include/lldb/Core/DataExtractor.h | 104 +- include/lldb/Core/Debugger.h | 111 +- include/lldb/Core/Disassembler.h | 36 +- include/lldb/Core/EmulateInstruction.h | 21 +- include/lldb/Core/Event.h | 24 +- include/lldb/Core/FileLineResolver.h | 17 +- include/lldb/Core/FormatEntity.h | 24 +- include/lldb/Core/History.h | 39 +- include/lldb/Core/IOHandler.h | 86 +- include/lldb/Core/Language.h | 117 - include/lldb/Core/Listener.h | 39 +- include/lldb/Core/Log.h | 8 +- include/lldb/Core/Logging.h | 1 + include/lldb/Core/MappedHash.h | 47 +- include/lldb/Core/Module.h | 96 +- include/lldb/Core/ModuleList.h | 32 +- include/lldb/Core/ModuleSpec.h | 64 +- include/lldb/Core/Opcode.h | 18 +- include/lldb/Core/PluginManager.h | 178 +- include/lldb/Core/RangeMap.h | 174 +- include/lldb/Core/RegisterValue.h | 131 +- include/lldb/Core/RegularExpression.h | 21 +- include/lldb/Core/STLUtils.h | 26 +- include/lldb/Core/Scalar.h | 123 +- include/lldb/Core/SearchFilter.h | 17 +- include/lldb/Core/Section.h | 43 +- include/lldb/Core/SourceManager.h | 66 +- include/lldb/Core/Stream.h | 28 +- include/lldb/Core/StreamAsynchronousIO.h | 14 +- include/lldb/Core/StreamCallback.h | 14 +- include/lldb/Core/StreamFile.h | 13 +- include/lldb/Core/StreamGDBRemote.h | 5 +- include/lldb/Core/StreamString.h | 15 +- include/lldb/Core/StreamTee.h | 15 +- include/lldb/Core/StringList.h | 15 +- include/lldb/Core/StructuredData.h | 228 +- include/lldb/Core/ThreadSafeDenseMap.h | 22 +- include/lldb/Core/ThreadSafeDenseSet.h | 7 + include/lldb/Core/Timer.h | 43 +- include/lldb/Core/UUID.h | 5 +- include/lldb/Core/UniqueCStringMap.h | 30 +- include/lldb/Core/Value.h | 41 +- include/lldb/Core/ValueObject.h | 173 +- include/lldb/Core/ValueObjectCast.h | 66 +- include/lldb/Core/ValueObjectChild.h | 77 +- include/lldb/Core/ValueObjectConstResult.h | 103 +- include/lldb/Core/ValueObjectConstResultCast.h | 76 + include/lldb/Core/ValueObjectConstResultChild.h | 39 +- include/lldb/Core/ValueObjectConstResultImpl.h | 29 +- include/lldb/Core/ValueObjectDynamicValue.h | 135 +- include/lldb/Core/ValueObjectList.h | 1 - include/lldb/Core/ValueObjectMemory.h | 51 +- include/lldb/Core/ValueObjectRegister.h | 138 +- include/lldb/Core/ValueObjectSyntheticFilter.h | 170 +- include/lldb/Core/ValueObjectVariable.h | 75 +- include/lldb/Core/dwarf.h | 6 +- .../lldb/DataFormatters/CXXFormatterFunctions.h | 375 - include/lldb/DataFormatters/CXXFunctionPointer.h | 23 + include/lldb/DataFormatters/DataVisualization.h | 25 +- .../lldb/DataFormatters/DumpValueObjectOptions.h | 185 + include/lldb/DataFormatters/FormatCache.h | 1 - include/lldb/DataFormatters/FormatClasses.h | 84 +- include/lldb/DataFormatters/FormatManager.h | 165 +- include/lldb/DataFormatters/FormattersContainer.h | 70 +- include/lldb/DataFormatters/FormattersHelpers.h | 279 + include/lldb/DataFormatters/LanguageCategory.h | 99 + include/lldb/DataFormatters/StringPrinter.h | 765 +- include/lldb/DataFormatters/TypeCategory.h | 302 +- include/lldb/DataFormatters/TypeCategoryMap.h | 37 +- include/lldb/DataFormatters/TypeFormat.h | 43 +- include/lldb/DataFormatters/TypeSummary.h | 190 +- include/lldb/DataFormatters/TypeSynthetic.h | 199 +- include/lldb/DataFormatters/TypeValidator.h | 20 +- include/lldb/DataFormatters/ValueObjectPrinter.h | 282 +- include/lldb/DataFormatters/VectorIterator.h | 53 + include/lldb/Expression/ASTDumper.h | 43 - include/lldb/Expression/ASTResultSynthesizer.h | 184 - include/lldb/Expression/ASTStructExtractor.h | 156 - include/lldb/Expression/ClangASTSource.h | 525 -- include/lldb/Expression/ClangExpression.h | 153 - include/lldb/Expression/ClangExpressionDeclMap.h | 705 -- include/lldb/Expression/ClangExpressionParser.h | 156 - include/lldb/Expression/ClangExpressionVariable.h | 456 -- include/lldb/Expression/ClangFunction.h | 451 -- include/lldb/Expression/ClangModulesDeclVendor.h | 129 - include/lldb/Expression/ClangPersistentVariables.h | 91 - include/lldb/Expression/ClangUserExpression.h | 365 - include/lldb/Expression/ClangUtilityFunction.h | 179 - include/lldb/Expression/DWARFExpression.h | 45 +- include/lldb/Expression/Expression.h | 141 + include/lldb/Expression/ExpressionParser.h | 123 + .../lldb/Expression/ExpressionTypeSystemHelper.h | 54 + include/lldb/Expression/ExpressionVariable.h | 320 + include/lldb/Expression/FunctionCaller.h | 395 + include/lldb/Expression/IRDynamicChecks.h | 20 +- include/lldb/Expression/IRExecutionUnit.h | 74 +- include/lldb/Expression/IRForTarget.h | 745 -- include/lldb/Expression/IRInterpreter.h | 1 - include/lldb/Expression/IRMemoryMap.h | 9 +- include/lldb/Expression/IRToDWARF.h | 111 - include/lldb/Expression/LLVMUserExpression.h | 118 + include/lldb/Expression/Materializer.h | 73 +- include/lldb/Expression/REPL.h | 211 + include/lldb/Expression/UserExpression.h | 335 + include/lldb/Expression/UtilityFunction.h | 162 + include/lldb/Host/Condition.h | 25 +- include/lldb/Host/Config.h | 6 +- include/lldb/Host/Debug.h | 16 +- include/lldb/Host/Endian.h | 4 +- include/lldb/Host/File.h | 82 +- include/lldb/Host/FileSpec.h | 41 +- include/lldb/Host/FileSystem.h | 5 + include/lldb/Host/HostGetOpt.h | 4 +- include/lldb/Host/HostInfo.h | 3 + include/lldb/Host/HostNativeThread.h | 2 + include/lldb/Host/HostNativeThreadForward.h | 3 + include/lldb/Host/MainLoopBase.h | 12 +- include/lldb/Host/MonitoringProcessLauncher.h | 11 +- include/lldb/Host/Mutex.h | 39 +- include/lldb/Host/OptionParser.h | 3 +- include/lldb/Host/Predicate.h | 45 +- include/lldb/Host/ProcessRunLock.h | 22 +- include/lldb/Host/Socket.h | 63 +- include/lldb/Host/Symbols.h | 2 +- include/lldb/Host/XML.h | 13 +- include/lldb/Host/common/GetOptInc.h | 65 + include/lldb/Host/common/NativeProcessProtocol.h | 17 +- include/lldb/Host/common/TCPSocket.h | 46 + include/lldb/Host/common/UDPSocket.h | 35 + include/lldb/Host/netbsd/Config.h | 28 + include/lldb/Host/netbsd/HostInfoNetBSD.h | 30 + include/lldb/Host/netbsd/HostThreadNetBSD.h | 32 + .../Host/posix/ConnectionFileDescriptorPosix.h | 15 +- include/lldb/Host/posix/DomainSocket.h | 37 + include/lldb/Host/posix/HostProcessPosix.h | 11 +- include/lldb/Host/posix/HostThreadPosix.h | 7 +- include/lldb/Host/posix/LockFilePosix.h | 6 +- include/lldb/Host/posix/MainLoopPosix.h | 2 +- .../lldb/Initialization/SystemInitializerCommon.h | 7 +- include/lldb/Interpreter/Args.h | 3 + include/lldb/Interpreter/CommandCompletions.h | 76 +- include/lldb/Interpreter/CommandHistory.h | 1 - include/lldb/Interpreter/CommandInterpreter.h | 82 +- include/lldb/Interpreter/CommandObject.h | 86 +- include/lldb/Interpreter/CommandObjectMultiword.h | 229 +- .../lldb/Interpreter/CommandObjectRegexCommand.h | 6 +- include/lldb/Interpreter/CommandOptionValidators.h | 13 +- include/lldb/Interpreter/CommandReturnObject.h | 8 +- include/lldb/Interpreter/OptionGroupArchitecture.h | 35 +- include/lldb/Interpreter/OptionGroupBoolean.h | 29 +- include/lldb/Interpreter/OptionGroupFile.h | 56 +- include/lldb/Interpreter/OptionGroupFormat.h | 30 +- include/lldb/Interpreter/OptionGroupOutputFile.h | 30 +- include/lldb/Interpreter/OptionGroupPlatform.h | 28 +- include/lldb/Interpreter/OptionGroupString.h | 32 +- include/lldb/Interpreter/OptionGroupUInt64.h | 33 +- include/lldb/Interpreter/OptionGroupUUID.h | 28 +- .../Interpreter/OptionGroupValueObjectDisplay.h | 47 +- include/lldb/Interpreter/OptionGroupVariable.h | 28 +- include/lldb/Interpreter/OptionGroupWatchpoint.h | 32 +- include/lldb/Interpreter/OptionValue.h | 18 +- include/lldb/Interpreter/OptionValueArch.h | 41 +- include/lldb/Interpreter/OptionValueArgs.h | 9 +- include/lldb/Interpreter/OptionValueArray.h | 41 +- include/lldb/Interpreter/OptionValueBoolean.h | 41 +- include/lldb/Interpreter/OptionValueChar.h | 28 +- include/lldb/Interpreter/OptionValueDictionary.h | 53 +- include/lldb/Interpreter/OptionValueEnumeration.h | 42 +- include/lldb/Interpreter/OptionValueFileSpec.h | 41 +- include/lldb/Interpreter/OptionValueFileSpecList.h | 32 +- include/lldb/Interpreter/OptionValueFormat.h | 27 +- include/lldb/Interpreter/OptionValueFormatEntity.h | 6 +- include/lldb/Interpreter/OptionValueLanguage.h | 5 +- include/lldb/Interpreter/OptionValuePathMappings.h | 31 +- include/lldb/Interpreter/OptionValueProperties.h | 83 +- include/lldb/Interpreter/OptionValueRegex.h | 39 +- include/lldb/Interpreter/OptionValueSInt64.h | 27 +- include/lldb/Interpreter/OptionValueString.h | 53 +- include/lldb/Interpreter/OptionValueUInt64.h | 27 +- include/lldb/Interpreter/OptionValueUUID.h | 41 +- include/lldb/Interpreter/Options.h | 63 +- include/lldb/Interpreter/PythonDataObjects.h | 280 - include/lldb/Interpreter/ScriptInterpreter.h | 41 +- include/lldb/Interpreter/ScriptInterpreterNone.h | 35 - include/lldb/Interpreter/ScriptInterpreterPython.h | 563 -- include/lldb/Symbol/ArmUnwindInfo.h | 77 + include/lldb/Symbol/Block.h | 70 +- include/lldb/Symbol/ClangASTContext.h | 941 ++- include/lldb/Symbol/ClangASTImporter.h | 53 +- include/lldb/Symbol/ClangASTType.h | 684 -- .../lldb/Symbol/ClangExternalASTSourceCallbacks.h | 38 +- include/lldb/Symbol/ClangExternalASTSourceCommon.h | 21 +- include/lldb/Symbol/ClangNamespaceDecl.h | 105 - include/lldb/Symbol/CompileUnit.h | 61 +- include/lldb/Symbol/CompilerDecl.h | 135 + include/lldb/Symbol/CompilerDeclContext.h | 146 + include/lldb/Symbol/CompilerType.h | 571 ++ include/lldb/Symbol/DebugMacros.h | 140 + include/lldb/Symbol/FuncUnwinders.h | 5 + include/lldb/Symbol/Function.h | 78 +- include/lldb/Symbol/GoASTContext.h | 402 + include/lldb/Symbol/LineEntry.h | 26 + include/lldb/Symbol/LineTable.h | 27 +- include/lldb/Symbol/ObjectContainer.h | 16 +- include/lldb/Symbol/ObjectFile.h | 18 +- include/lldb/Symbol/Symbol.h | 19 +- include/lldb/Symbol/SymbolContext.h | 73 +- include/lldb/Symbol/SymbolContextScope.h | 13 +- include/lldb/Symbol/SymbolFile.h | 49 +- include/lldb/Symbol/SymbolVendor.h | 35 +- include/lldb/Symbol/TaggedASTType.h | 18 +- include/lldb/Symbol/Type.h | 259 +- include/lldb/Symbol/TypeList.h | 13 +- include/lldb/Symbol/TypeMap.h | 98 + include/lldb/Symbol/TypeSystem.h | 604 ++ include/lldb/Symbol/UnwindPlan.h | 40 +- include/lldb/Symbol/UnwindTable.h | 10 +- include/lldb/Symbol/Variable.h | 26 +- include/lldb/Symbol/VariableList.h | 4 +- include/lldb/Target/ABI.h | 12 +- include/lldb/Target/CPPLanguageRuntime.h | 130 +- include/lldb/Target/DynamicLoader.h | 21 +- include/lldb/Target/ExecutionContext.h | 111 +- .../lldb/Target/InstrumentationRuntimeStopInfo.h | 19 +- include/lldb/Target/JITLoader.h | 3 +- include/lldb/Target/Language.h | 206 + include/lldb/Target/LanguageRuntime.h | 50 +- include/lldb/Target/ObjCLanguageRuntime.h | 269 +- include/lldb/Target/OperatingSystem.h | 6 +- include/lldb/Target/Platform.h | 280 +- include/lldb/Target/Process.h | 550 +- include/lldb/Target/QueueItem.h | 20 +- include/lldb/Target/RegisterContext.h | 28 +- include/lldb/Target/SectionLoadList.h | 1 + include/lldb/Target/StackFrame.h | 58 +- include/lldb/Target/StackFrameList.h | 22 +- include/lldb/Target/StackID.h | 20 +- include/lldb/Target/StopInfo.h | 4 +- include/lldb/Target/SystemRuntime.h | 6 +- include/lldb/Target/Target.h | 351 +- include/lldb/Target/TargetList.h | 28 +- include/lldb/Target/Thread.h | 164 +- include/lldb/Target/ThreadList.h | 10 +- include/lldb/Target/ThreadPlan.h | 54 +- include/lldb/Target/ThreadPlanBase.h | 32 +- include/lldb/Target/ThreadPlanCallFunction.h | 77 +- .../lldb/Target/ThreadPlanCallFunctionUsingABI.h | 5 +- include/lldb/Target/ThreadPlanCallUserExpression.h | 31 +- include/lldb/Target/ThreadPlanPython.h | 48 +- include/lldb/Target/ThreadPlanRunToAddress.h | 43 +- include/lldb/Target/ThreadPlanShouldStopHere.h | 16 +- include/lldb/Target/ThreadPlanStepInRange.h | 26 +- include/lldb/Target/ThreadPlanStepInstruction.h | 24 +- include/lldb/Target/ThreadPlanStepOut.h | 33 +- include/lldb/Target/ThreadPlanStepOverBreakpoint.h | 35 +- include/lldb/Target/ThreadPlanStepOverRange.h | 23 +- include/lldb/Target/ThreadPlanStepRange.h | 28 +- include/lldb/Target/ThreadPlanStepThrough.h | 26 +- include/lldb/Target/ThreadPlanStepUntil.h | 28 +- include/lldb/Target/ThreadPlanTracer.h | 23 +- include/lldb/Target/ThreadSpec.h | 14 +- include/lldb/Target/UnixSignals.h | 13 +- include/lldb/Target/UnwindAssembly.h | 7 +- include/lldb/Utility/AnsiTerminal.h | 9 +- include/lldb/Utility/Either.h | 154 + include/lldb/Utility/Iterable.h | 25 +- include/lldb/Utility/JSON.h | 127 +- include/lldb/Utility/ProcessStructReader.h | 8 +- include/lldb/Utility/PseudoTerminal.h | 2 +- include/lldb/Utility/PythonPointer.h | 73 - include/lldb/Utility/SharedCluster.h | 6 +- include/lldb/Utility/SharingPtr.h | 79 +- include/lldb/Utility/StringExtractor.h | 3 + include/lldb/Utility/TaskPool.h | 221 + include/lldb/lldb-defines.h | 2 + include/lldb/lldb-enumerations.h | 41 +- include/lldb/lldb-forward.h | 50 +- include/lldb/lldb-private-enumerations.h | 28 +- include/lldb/lldb-private-interfaces.h | 10 +- include/lldb/lldb-private-types.h | 18 +- include/lldb/lldb-python.h | 31 - include/lldb/lldb-types.h | 2 +- source/API/SBAttachInfo.cpp | 16 + source/API/SBBreakpoint.cpp | 48 +- source/API/SBCommandInterpreter.cpp | 152 +- source/API/SBCommandReturnObject.cpp | 112 +- source/API/SBDebugger.cpp | 250 +- source/API/SBFrame.cpp | 133 +- source/API/SBFunction.cpp | 30 +- source/API/SBLanguageRuntime.cpp | 6 +- source/API/SBModule.cpp | 24 +- source/API/SBPlatform.cpp | 2 +- source/API/SBProcess.cpp | 46 +- source/API/SBStream.cpp | 7 + source/API/SBTarget.cpp | 137 +- source/API/SBThread.cpp | 20 +- source/API/SBType.cpp | 148 +- source/API/SBTypeCategory.cpp | 25 +- source/API/SBTypeEnumMember.cpp | 3 +- source/API/SBTypeNameSpecifier.cpp | 4 +- source/API/SBTypeSummary.cpp | 151 +- source/API/SBValue.cpp | 47 +- source/API/SBValueList.cpp | 4 +- source/API/SystemInitializerFull.cpp | 96 +- source/API/liblldb.exports | 3 + source/API/liblldb.xcode.exports | 3 + source/Breakpoint/Breakpoint.cpp | 55 +- source/Breakpoint/BreakpointID.cpp | 17 +- source/Breakpoint/BreakpointIDList.cpp | 20 +- source/Breakpoint/BreakpointLocation.cpp | 105 +- source/Breakpoint/BreakpointLocationList.cpp | 16 +- source/Breakpoint/BreakpointOptions.cpp | 29 +- source/Breakpoint/BreakpointResolverAddress.cpp | 90 +- source/Breakpoint/BreakpointResolverName.cpp | 103 +- source/Breakpoint/BreakpointSite.cpp | 29 +- source/Breakpoint/StoppointCallbackContext.cpp | 7 +- source/Breakpoint/Watchpoint.cpp | 83 +- source/Breakpoint/WatchpointList.cpp | 7 +- source/Breakpoint/WatchpointOptions.cpp | 26 +- source/Commands/CommandObjectApropos.h | 13 +- source/Commands/CommandObjectArgs.cpp | 27 +- source/Commands/CommandObjectArgs.h | 28 +- source/Commands/CommandObjectBreakpoint.cpp | 232 +- source/Commands/CommandObjectBreakpoint.h | 5 +- source/Commands/CommandObjectBreakpointCommand.cpp | 59 +- source/Commands/CommandObjectBreakpointCommand.h | 8 +- source/Commands/CommandObjectBugreport.cpp | 2 +- source/Commands/CommandObjectBugreport.h | 5 +- source/Commands/CommandObjectCommands.cpp | 171 +- source/Commands/CommandObjectCommands.h | 6 +- source/Commands/CommandObjectDisassemble.cpp | 2 +- source/Commands/CommandObjectDisassemble.h | 30 +- source/Commands/CommandObjectExpression.cpp | 100 +- source/Commands/CommandObjectExpression.h | 46 +- source/Commands/CommandObjectFrame.cpp | 52 +- source/Commands/CommandObjectFrame.h | 6 +- source/Commands/CommandObjectGUI.h | 12 +- source/Commands/CommandObjectHelp.h | 43 +- source/Commands/CommandObjectLanguage.cpp | 5 +- source/Commands/CommandObjectLanguage.h | 10 +- source/Commands/CommandObjectLog.cpp | 41 +- source/Commands/CommandObjectLog.h | 5 +- source/Commands/CommandObjectMemory.cpp | 181 +- source/Commands/CommandObjectMemory.h | 6 +- source/Commands/CommandObjectMultiword.cpp | 8 + source/Commands/CommandObjectPlatform.cpp | 274 +- source/Commands/CommandObjectPlatform.h | 7 +- source/Commands/CommandObjectPlugin.cpp | 6 +- source/Commands/CommandObjectPlugin.h | 6 +- source/Commands/CommandObjectProcess.cpp | 315 +- source/Commands/CommandObjectProcess.h | 6 +- source/Commands/CommandObjectQuit.h | 12 +- source/Commands/CommandObjectRegister.cpp | 35 +- source/Commands/CommandObjectRegister.h | 5 +- source/Commands/CommandObjectSettings.cpp | 134 +- source/Commands/CommandObjectSettings.h | 6 +- source/Commands/CommandObjectSource.cpp | 32 +- source/Commands/CommandObjectSource.h | 6 +- source/Commands/CommandObjectSyntax.h | 13 +- source/Commands/CommandObjectTarget.cpp | 332 +- source/Commands/CommandObjectTarget.h | 7 +- source/Commands/CommandObjectThread.cpp | 182 +- source/Commands/CommandObjectThread.h | 6 +- source/Commands/CommandObjectType.cpp | 2823 +++---- source/Commands/CommandObjectType.h | 6 +- source/Commands/CommandObjectVersion.h | 12 +- source/Commands/CommandObjectWatchpoint.cpp | 128 +- source/Commands/CommandObjectWatchpoint.h | 6 +- source/Commands/CommandObjectWatchpointCommand.cpp | 45 +- source/Commands/CommandObjectWatchpointCommand.h | 7 +- source/Core/Address.cpp | 32 +- source/Core/AddressResolverName.cpp | 1 - source/Core/ArchSpec.cpp | 174 +- source/Core/ConnectionSharedMemory.cpp | 2 +- source/Core/ConstString.cpp | 145 +- source/Core/CxaDemangle.cpp | 2 + source/Core/DataEncoder.cpp | 10 +- source/Core/DataExtractor.cpp | 97 +- source/Core/Debugger.cpp | 146 +- source/Core/Disassembler.cpp | 17 +- source/Core/DynamicLoader.cpp | 46 +- source/Core/EmulateInstruction.cpp | 8 +- source/Core/Event.cpp | 2 +- source/Core/FastDemangle.cpp | 2 +- source/Core/FormatEntity.cpp | 399 +- source/Core/IOHandler.cpp | 184 +- source/Core/Language.cpp | 169 - source/Core/Log.cpp | 3 +- source/Core/Logging.cpp | 3 + source/Core/Mangled.cpp | 37 +- source/Core/Module.cpp | 222 +- source/Core/ModuleList.cpp | 83 +- source/Core/Opcode.cpp | 2 +- source/Core/PluginManager.cpp | 716 +- source/Core/RegisterValue.cpp | 583 +- source/Core/RegularExpression.cpp | 3 +- source/Core/Scalar.cpp | 2576 +++--- source/Core/Section.cpp | 19 + source/Core/SourceManager.cpp | 25 +- source/Core/Stream.cpp | 20 +- source/Core/StreamAsynchronousIO.cpp | 2 +- source/Core/StreamString.cpp | 2 +- source/Core/Timer.cpp | 73 +- source/Core/Value.cpp | 58 +- source/Core/ValueObject.cpp | 607 +- source/Core/ValueObjectCast.cpp | 27 +- source/Core/ValueObjectChild.cpp | 119 +- source/Core/ValueObjectConstResult.cpp | 59 +- source/Core/ValueObjectConstResultCast.cpp | 75 + source/Core/ValueObjectConstResultChild.cpp | 21 +- source/Core/ValueObjectConstResultImpl.cpp | 66 +- source/Core/ValueObjectDynamicValue.cpp | 142 +- source/Core/ValueObjectMemory.cpp | 47 +- source/Core/ValueObjectRegister.cpp | 51 +- source/Core/ValueObjectSyntheticFilter.cpp | 92 +- source/Core/ValueObjectVariable.cpp | 27 +- source/DataFormatters/CF.cpp | 297 - source/DataFormatters/CXXFormatterFunctions.cpp | 1228 --- source/DataFormatters/CXXFunctionPointer.cpp | 66 + source/DataFormatters/Cocoa.cpp | 561 -- source/DataFormatters/CoreMedia.cpp | 85 - source/DataFormatters/DataVisualization.cpp | 34 +- source/DataFormatters/DumpValueObjectOptions.cpp | 245 + source/DataFormatters/FormatClasses.cpp | 47 + source/DataFormatters/FormatManager.cpp | 1156 +-- source/DataFormatters/FormattersHelpers.cpp | 336 + source/DataFormatters/LanguageCategory.cpp | 271 + source/DataFormatters/LibCxx.cpp | 463 -- source/DataFormatters/LibCxxInitializerList.cpp | 143 - source/DataFormatters/LibCxxList.cpp | 369 - source/DataFormatters/LibCxxMap.cpp | 452 -- source/DataFormatters/LibCxxUnorderedMap.cpp | 172 - source/DataFormatters/LibCxxVector.cpp | 155 - source/DataFormatters/LibStdcpp.cpp | 160 - source/DataFormatters/NSArray.cpp | 706 -- source/DataFormatters/NSDictionary.cpp | 702 -- source/DataFormatters/NSIndexPath.cpp | 338 - source/DataFormatters/NSSet.cpp | 717 -- source/DataFormatters/StringPrinter.cpp | 307 +- source/DataFormatters/TypeCategory.cpp | 151 +- source/DataFormatters/TypeCategoryMap.cpp | 105 +- source/DataFormatters/TypeFormat.cpp | 26 +- source/DataFormatters/TypeSummary.cpp | 44 +- source/DataFormatters/TypeSynthetic.cpp | 20 +- source/DataFormatters/ValueObjectPrinter.cpp | 444 +- source/DataFormatters/VectorType.cpp | 128 +- source/Expression/ASTDumper.cpp | 132 - source/Expression/ASTResultSynthesizer.cpp | 512 -- source/Expression/ASTStructExtractor.cpp | 220 - source/Expression/ClangASTSource.cpp | 2075 ----- source/Expression/ClangExpressionDeclMap.cpp | 2171 ----- source/Expression/ClangExpressionParser.cpp | 621 -- source/Expression/ClangExpressionVariable.cpp | 142 - source/Expression/ClangFunction.cpp | 596 -- source/Expression/ClangModulesDeclVendor.cpp | 731 -- source/Expression/ClangPersistentVariables.cpp | 89 - source/Expression/ClangUserExpression.cpp | 1172 --- source/Expression/ClangUtilityFunction.cpp | 198 - source/Expression/DWARFExpression.cpp | 659 +- source/Expression/Expression.cpp | 32 + source/Expression/ExpressionSourceCode.cpp | 145 +- source/Expression/ExpressionVariable.cpp | 36 + source/Expression/FunctionCaller.cpp | 406 + source/Expression/IRDynamicChecks.cpp | 100 +- source/Expression/IRExecutionUnit.cpp | 22 +- source/Expression/IRForTarget.cpp | 2819 ------- source/Expression/IRInterpreter.cpp | 16 +- source/Expression/IRMemoryMap.cpp | 21 +- source/Expression/LLVMUserExpression.cpp | 363 + source/Expression/Materializer.cpp | 303 +- source/Expression/REPL.cpp | 649 ++ source/Expression/UserExpression.cpp | 348 + source/Expression/UtilityFunction.cpp | 124 + source/Host/common/Editline.cpp | 52 +- source/Host/common/File.cpp | 22 +- source/Host/common/FileSpec.cpp | 26 +- source/Host/common/GetOptInc.cpp | 473 ++ source/Host/common/Host.cpp | 10 +- source/Host/common/HostInfoBase.cpp | 24 +- source/Host/common/Mutex.cpp | 2 +- source/Host/common/NativeProcessProtocol.cpp | 8 +- source/Host/common/OptionParser.cpp | 4 +- source/Host/common/Socket.cpp | 622 +- source/Host/common/SocketAddress.cpp | 6 +- source/Host/common/Symbols.cpp | 68 +- source/Host/common/TCPSocket.cpp | 288 + source/Host/common/ThisThread.cpp | 2 +- source/Host/common/UDPSocket.cpp | 158 + source/Host/common/XML.cpp | 6 +- source/Host/freebsd/Host.cpp | 2 +- source/Host/netbsd/Host.cpp | 287 + source/Host/netbsd/HostInfoNetBSD.cpp | 112 + source/Host/netbsd/HostThreadNetBSD.cpp | 50 + source/Host/netbsd/ThisThread.cpp | 30 + .../Host/posix/ConnectionFileDescriptorPosix.cpp | 108 +- source/Host/posix/DomainSocket.cpp | 133 + source/Host/posix/FileSystem.cpp | 57 + source/Host/posix/HostInfoPosix.cpp | 21 +- source/Host/posix/MainLoopPosix.cpp | 6 +- source/Host/posix/PipePosix.cpp | 10 +- source/Initialization/SystemInitializerCommon.cpp | 27 +- source/Interpreter/Args.cpp | 47 +- source/Interpreter/CommandInterpreter.cpp | 121 +- source/Interpreter/CommandObject.cpp | 6 +- source/Interpreter/CommandObjectScript.h | 14 +- .../Interpreter/OptionGroupValueObjectDisplay.cpp | 2 +- source/Interpreter/OptionValueLanguage.cpp | 29 +- source/Interpreter/OptionValueProperties.cpp | 9 + source/Interpreter/Property.cpp | 4 +- source/Interpreter/PythonDataObjects.cpp | 524 -- source/Interpreter/ScriptInterpreterNone.cpp | 42 - source/Interpreter/ScriptInterpreterPython.cpp | 3194 -------- source/Interpreter/embedded_interpreter.py | 15 +- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 317 +- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h | 81 +- .../Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 170 +- source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h | 72 +- source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp | 397 +- source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h | 84 +- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp | 262 +- source/Plugins/ABI/SysV-arm/ABISysV_arm.h | 16 +- source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp | 31 +- source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h | 17 +- .../Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp | 38 +- source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h | 117 +- source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp | 495 +- source/Plugins/ABI/SysV-i386/ABISysV_i386.h | 37 +- source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp | 327 +- source/Plugins/ABI/SysV-mips/ABISysV_mips.h | 96 +- source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp | 542 +- source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h | 88 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 347 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h | 98 +- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 348 +- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h | 98 +- source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 475 +- source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h | 88 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 236 +- .../Plugins/Disassembler/llvm/DisassemblerLLVMC.h | 57 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 37 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.h | 66 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp | 42 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 63 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 76 +- .../DynamicLoader/Static/DynamicLoaderStatic.h | 42 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 42 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.h | 25 +- .../Plugins/ExpressionParser/Clang/ASTDumper.cpp | 134 + source/Plugins/ExpressionParser/Clang/ASTDumper.h | 42 + .../Clang/ASTResultSynthesizer.cpp | 514 ++ .../ExpressionParser/Clang/ASTResultSynthesizer.h | 185 + .../ExpressionParser/Clang/ASTStructExtractor.cpp | 221 + .../ExpressionParser/Clang/ASTStructExtractor.h | 158 + .../ExpressionParser/Clang/ClangASTSource.cpp | 2101 +++++ .../ExpressionParser/Clang/ClangASTSource.h | 526 ++ .../Clang/ClangExpressionDeclMap.cpp | 2351 ++++++ .../Clang/ClangExpressionDeclMap.h | 714 ++ .../ExpressionParser/Clang/ClangExpressionHelper.h | 79 + .../Clang/ClangExpressionParser.cpp | 657 ++ .../ExpressionParser/Clang/ClangExpressionParser.h | 136 + .../Clang/ClangExpressionVariable.cpp | 76 + .../Clang/ClangExpressionVariable.h | 265 + .../ExpressionParser/Clang/ClangFunctionCaller.cpp | 221 + .../ExpressionParser/Clang/ClangFunctionCaller.h | 173 + .../Clang/ClangModulesDeclVendor.cpp | 731 ++ .../Clang/ClangModulesDeclVendor.h | 128 + .../Clang/ClangPersistentVariables.cpp | 84 + .../Clang/ClangPersistentVariables.h | 106 + .../ExpressionParser/Clang/ClangUserExpression.cpp | 673 ++ .../ExpressionParser/Clang/ClangUserExpression.h | 218 + .../Clang/ClangUtilityFunction.cpp | 189 + .../ExpressionParser/Clang/ClangUtilityFunction.h | 137 + .../Plugins/ExpressionParser/Clang/IRForTarget.cpp | 2820 +++++++ .../Plugins/ExpressionParser/Clang/IRForTarget.h | 745 ++ source/Plugins/ExpressionParser/Go/GoAST.h | 3225 ++++++++ source/Plugins/ExpressionParser/Go/GoLexer.cpp | 402 + source/Plugins/ExpressionParser/Go/GoLexer.h | 201 + source/Plugins/ExpressionParser/Go/GoParser.cpp | 1035 +++ source/Plugins/ExpressionParser/Go/GoParser.h | 165 + .../ExpressionParser/Go/GoUserExpression.cpp | 756 ++ .../Plugins/ExpressionParser/Go/GoUserExpression.h | 98 + source/Plugins/ExpressionParser/Go/gen_go_ast.py | 356 + .../Instruction/ARM/EmulateInstructionARM.cpp | 406 +- .../Instruction/ARM/EmulateInstructionARM.h | 48 +- .../Instruction/ARM64/EmulateInstructionARM64.cpp | 304 +- .../Instruction/ARM64/EmulateInstructionARM64.h | 93 +- .../Instruction/MIPS/EmulateInstructionMIPS.cpp | 2005 ++++- .../Instruction/MIPS/EmulateInstructionMIPS.h | 132 +- .../MIPS64/EmulateInstructionMIPS64.cpp | 1119 ++- .../Instruction/MIPS64/EmulateInstructionMIPS64.h | 114 +- .../AddressSanitizer/AddressSanitizerRuntime.cpp | 74 +- .../AddressSanitizer/AddressSanitizerRuntime.h | 48 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 77 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.h | 36 +- .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 792 ++ .../Plugins/Language/CPlusPlus/CPlusPlusLanguage.h | 186 + .../Plugins/Language/CPlusPlus/CxxStringTypes.cpp | 204 + source/Plugins/Language/CPlusPlus/CxxStringTypes.h | 41 + source/Plugins/Language/CPlusPlus/LibCxx.cpp | 653 ++ source/Plugins/Language/CPlusPlus/LibCxx.h | 141 + .../Language/CPlusPlus/LibCxxInitializerList.cpp | 147 + source/Plugins/Language/CPlusPlus/LibCxxList.cpp | 414 + source/Plugins/Language/CPlusPlus/LibCxxMap.cpp | 478 ++ .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 172 + source/Plugins/Language/CPlusPlus/LibCxxVector.cpp | 159 + source/Plugins/Language/CPlusPlus/LibStdcpp.cpp | 373 + source/Plugins/Language/CPlusPlus/LibStdcpp.h | 33 + .../Plugins/Language/Go/GoFormatterFunctions.cpp | 173 + source/Plugins/Language/Go/GoFormatterFunctions.h | 43 + source/Plugins/Language/Go/GoLanguage.cpp | 146 + source/Plugins/Language/Go/GoLanguage.h | 66 + source/Plugins/Language/ObjC/CF.cpp | 334 + source/Plugins/Language/ObjC/CF.h | 34 + source/Plugins/Language/ObjC/Cocoa.cpp | 967 +++ source/Plugins/Language/ObjC/Cocoa.h | 97 + source/Plugins/Language/ObjC/CoreMedia.cpp | 89 + source/Plugins/Language/ObjC/CoreMedia.h | 26 + source/Plugins/Language/ObjC/NSArray.cpp | 792 ++ source/Plugins/Language/ObjC/NSDictionary.cpp | 749 ++ source/Plugins/Language/ObjC/NSDictionary.h | 48 + source/Plugins/Language/ObjC/NSError.cpp | 218 + source/Plugins/Language/ObjC/NSException.cpp | 219 + source/Plugins/Language/ObjC/NSIndexPath.cpp | 349 + source/Plugins/Language/ObjC/NSSet.cpp | 758 ++ source/Plugins/Language/ObjC/NSSet.h | 40 + source/Plugins/Language/ObjC/NSString.cpp | 405 + source/Plugins/Language/ObjC/NSString.h | 42 + source/Plugins/Language/ObjC/ObjCLanguage.cpp | 877 ++ source/Plugins/Language/ObjC/ObjCLanguage.h | 210 + .../Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp | 68 + .../Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h | 63 + .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 49 +- .../ItaniumABI/ItaniumABILanguageRuntime.h | 83 +- .../LanguageRuntime/Go/GoLanguageRuntime.cpp | 238 + .../Plugins/LanguageRuntime/Go/GoLanguageRuntime.h | 93 + .../RenderScriptRuntime/RenderScriptRuntime.cpp | 3203 +++++++- .../RenderScriptRuntime/RenderScriptRuntime.h | 229 +- .../MemoryHistory/asan/MemoryHistoryASan.cpp | 108 +- .../Plugins/MemoryHistory/asan/MemoryHistoryASan.h | 34 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 10 +- .../BSD-Archive/ObjectContainerBSDArchive.h | 65 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 508 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 19 +- source/Plugins/ObjectFile/JIT/ObjectFileJIT.h | 114 +- .../OperatingSystem/Go/OperatingSystemGo.cpp | 559 ++ .../Plugins/OperatingSystem/Go/OperatingSystemGo.h | 87 + .../Python/OperatingSystemPython.cpp | 5 +- .../OperatingSystem/Python/OperatingSystemPython.h | 60 +- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h | 13 +- source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp | 685 ++ source/Plugins/Platform/NetBSD/PlatformNetBSD.h | 177 + source/Plugins/Platform/POSIX/PlatformPOSIX.cpp | 185 +- source/Plugins/Platform/POSIX/PlatformPOSIX.h | 60 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 125 +- .../Platform/gdb-server/PlatformRemoteGDBServer.h | 33 +- source/Plugins/Process/FreeBSD/FreeBSDThread.cpp | 623 +- source/Plugins/Process/FreeBSD/FreeBSDThread.h | 109 +- source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp | 2 +- source/Plugins/Process/FreeBSD/POSIXStopInfo.h | 8 +- source/Plugins/Process/FreeBSD/POSIXThread.cpp | 661 -- source/Plugins/Process/FreeBSD/POSIXThread.h | 132 - source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp | 829 +- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h | 197 +- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 6 +- source/Plugins/Process/FreeBSD/ProcessMonitor.h | 4 +- source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp | 939 --- source/Plugins/Process/FreeBSD/ProcessPOSIX.h | 205 - .../Plugins/Process/FreeBSD/RegisterContextPOSIX.h | 79 + .../RegisterContextPOSIXProcessMonitor_arm.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_arm.h | 1 + .../RegisterContextPOSIXProcessMonitor_arm64.cpp | 6 +- .../RegisterContextPOSIXProcessMonitor_arm64.h | 1 + .../RegisterContextPOSIXProcessMonitor_mips64.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_mips64.h | 1 + .../RegisterContextPOSIXProcessMonitor_powerpc.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_powerpc.h | 1 + .../RegisterContextPOSIXProcessMonitor_x86.cpp | 35 +- .../RegisterContextPOSIXProcessMonitor_x86.h | 2 + source/Plugins/Process/POSIX/CrashReason.cpp | 5 +- .../Process/Utility/DynamicRegisterInfo.cpp | 18 +- source/Plugins/Process/Utility/FreeBSDSignals.cpp | 132 +- source/Plugins/Process/Utility/HistoryThread.h | 47 +- source/Plugins/Process/Utility/HistoryUnwind.h | 20 +- .../Plugins/Process/Utility/InferiorCallPOSIX.cpp | 15 +- source/Plugins/Process/Utility/LinuxSignals.cpp | 134 +- .../Plugins/Process/Utility/MipsLinuxSignals.cpp | 134 +- source/Plugins/Process/Utility/NetBSDSignals.cpp | 34 + source/Plugins/Process/Utility/NetBSDSignals.h | 31 + .../Process/Utility/RegisterContextDarwin_arm.cpp | 184 +- .../Process/Utility/RegisterContextDarwin_arm.h | 76 +- .../Utility/RegisterContextDarwin_arm64.cpp | 114 +- .../Process/Utility/RegisterContextDarwin_arm64.h | 64 +- .../Process/Utility/RegisterContextDarwin_i386.cpp | 228 +- .../Process/Utility/RegisterContextDarwin_i386.h | 55 +- .../Utility/RegisterContextDarwin_x86_64.cpp | 406 +- .../Process/Utility/RegisterContextDarwin_x86_64.h | 52 +- .../Process/Utility/RegisterContextDummy.cpp | 4 +- .../Plugins/Process/Utility/RegisterContextDummy.h | 56 +- .../Process/Utility/RegisterContextFreeBSD_arm.cpp | 1 + .../Process/Utility/RegisterContextFreeBSD_arm.h | 1 - .../Process/Utility/RegisterContextFreeBSD_arm64.h | 2 +- .../Process/Utility/RegisterContextFreeBSD_i386.h | 2 +- .../Utility/RegisterContextFreeBSD_mips64.h | 2 +- .../Utility/RegisterContextFreeBSD_powerpc.h | 18 +- .../Utility/RegisterContextFreeBSD_x86_64.h | 2 +- .../Process/Utility/RegisterContextHistory.cpp | 4 +- .../Process/Utility/RegisterContextHistory.h | 55 +- .../Process/Utility/RegisterContextLLDB.cpp | 93 +- .../Plugins/Process/Utility/RegisterContextLLDB.h | 58 +- .../Process/Utility/RegisterContextLinux_arm.cpp | 1 + .../Process/Utility/RegisterContextLinux_arm.h | 1 - .../Process/Utility/RegisterContextLinux_arm64.cpp | 2 +- .../Process/Utility/RegisterContextLinux_arm64.h | 1 - .../Process/Utility/RegisterContextLinux_i386.cpp | 14 +- .../Process/Utility/RegisterContextLinux_i386.h | 8 +- .../Process/Utility/RegisterContextLinux_mips.cpp | 17 +- .../Process/Utility/RegisterContextLinux_mips.h | 5 +- .../Utility/RegisterContextLinux_mips64.cpp | 16 +- .../Process/Utility/RegisterContextLinux_mips64.h | 2 +- .../Utility/RegisterContextLinux_x86_64.cpp | 11 +- .../Process/Utility/RegisterContextLinux_x86_64.h | 7 +- .../Utility/RegisterContextMacOSXFrameBackchain.h | 57 +- .../Process/Utility/RegisterContextMemory.h | 61 +- .../Plugins/Process/Utility/RegisterContextPOSIX.h | 79 - .../Process/Utility/RegisterContextPOSIX_arm.cpp | 48 + .../Process/Utility/RegisterContextPOSIX_arm.h | 30 +- .../Process/Utility/RegisterContextPOSIX_arm64.h | 27 +- .../Process/Utility/RegisterContextPOSIX_mips64.h | 27 +- .../Process/Utility/RegisterContextPOSIX_powerpc.h | 29 +- .../Process/Utility/RegisterContextPOSIX_x86.h | 29 +- .../Process/Utility/RegisterContextThreadMemory.h | 104 +- .../Plugins/Process/Utility/RegisterContext_mips.h | 663 +- .../Process/Utility/RegisterContext_powerpc.h | 321 +- .../Plugins/Process/Utility/RegisterContext_x86.h | 411 +- .../Process/Utility/RegisterInfoInterface.h | 22 + source/Plugins/Process/Utility/RegisterInfos_arm.h | 334 +- .../Plugins/Process/Utility/RegisterInfos_arm64.h | 156 +- .../Plugins/Process/Utility/RegisterInfos_i386.h | 73 +- .../Plugins/Process/Utility/RegisterInfos_mips.h | 233 +- .../Plugins/Process/Utility/RegisterInfos_mips64.h | 319 +- .../Process/Utility/RegisterInfos_powerpc.h | 14 +- .../Plugins/Process/Utility/RegisterInfos_x86_64.h | 94 +- .../Process/Utility/StopInfoMachException.cpp | 4 + .../Process/Utility/StopInfoMachException.h | 16 +- source/Plugins/Process/Utility/ThreadMemory.h | 92 +- source/Plugins/Process/Utility/UnwindLLDB.cpp | 86 +- source/Plugins/Process/Utility/UnwindLLDB.h | 37 +- .../Process/Utility/UnwindMacOSXFrameBackchain.h | 28 +- .../Process/Utility/lldb-arm-register-enums.h | 50 +- source/Plugins/Process/elf-core/ProcessElfCore.cpp | 77 +- source/Plugins/Process/elf-core/ProcessElfCore.h | 32 +- .../elf-core/RegisterContextPOSIXCore_arm.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_arm.h | 40 +- .../elf-core/RegisterContextPOSIXCore_arm64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_arm64.h | 40 +- .../elf-core/RegisterContextPOSIXCore_mips64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_mips64.h | 40 +- .../elf-core/RegisterContextPOSIXCore_powerpc.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_powerpc.h | 42 +- .../elf-core/RegisterContextPOSIXCore_x86_64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_x86_64.h | 40 +- source/Plugins/Process/elf-core/ThreadElfCore.cpp | 5 +- source/Plugins/Process/elf-core/ThreadElfCore.h | 41 +- .../Process/gdb-remote/GDBRemoteCommunication.cpp | 232 +- .../Process/gdb-remote/GDBRemoteCommunication.h | 77 +- .../gdb-remote/GDBRemoteCommunicationClient.cpp | 287 +- .../gdb-remote/GDBRemoteCommunicationClient.h | 76 +- .../gdb-remote/GDBRemoteCommunicationServer.h | 8 +- .../GDBRemoteCommunicationServerCommon.cpp | 105 +- .../GDBRemoteCommunicationServerCommon.h | 17 +- .../GDBRemoteCommunicationServerLLGS.cpp | 600 +- .../gdb-remote/GDBRemoteCommunicationServerLLGS.h | 41 +- .../GDBRemoteCommunicationServerPlatform.cpp | 305 +- .../GDBRemoteCommunicationServerPlatform.h | 52 +- .../gdb-remote/GDBRemoteRegisterContext.cpp | 290 +- .../Process/gdb-remote/GDBRemoteRegisterContext.h | 22 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 1080 ++- .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 138 +- .../Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 8 + .../Plugins/Process/gdb-remote/ThreadGDBRemote.h | 32 +- .../None/ScriptInterpreterNone.cpp | 93 + .../ScriptInterpreter/None/ScriptInterpreterNone.h | 66 + .../ScriptInterpreter/Python/PythonDataObjects.cpp | 1069 +++ .../ScriptInterpreter/Python/PythonDataObjects.h | 498 ++ .../Python/PythonExceptionState.cpp | 201 + .../Python/PythonExceptionState.h | 70 + .../Python/ScriptInterpreterPython.cpp | 3172 ++++++++ .../Python/ScriptInterpreterPython.h | 607 ++ .../Plugins/ScriptInterpreter/Python/lldb-python.h | 31 + source/Plugins/SymbolFile/DWARF/DIERef.cpp | 56 + source/Plugins/SymbolFile/DWARF/DIERef.h | 42 + source/Plugins/SymbolFile/DWARF/DWARFASTParser.h | 65 + .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 4034 ++++++++++ .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 213 + .../Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp | 828 ++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h | 84 + source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp | 90 + source/Plugins/SymbolFile/DWARF/DWARFAttribute.h | 60 +- .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp | 459 +- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h | 124 +- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 543 ++ source/Plugins/SymbolFile/DWARF/DWARFDIE.h | 281 + .../SymbolFile/DWARF/DWARFDIECollection.cpp | 18 +- .../Plugins/SymbolFile/DWARF/DWARFDIECollection.h | 12 +- .../Plugins/SymbolFile/DWARF/DWARFDataExtractor.h | 5 +- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 230 +- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 35 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 953 +-- .../Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h | 138 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp | 95 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h | 9 +- .../Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp | 128 + source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h | 68 + .../SymbolFile/DWARF/DWARFDebugPubnames.cpp | 60 +- .../Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp | 54 +- source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h | 16 +- source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h | 7 + source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp | 114 +- source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 40 +- .../SymbolFile/DWARF/DWARFLocationDescription.cpp | 172 - .../SymbolFile/DWARF/DWARFLocationDescription.h | 24 - .../Plugins/SymbolFile/DWARF/DWARFLocationList.cpp | 94 - .../Plugins/SymbolFile/DWARF/DWARFLocationList.h | 34 - .../Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp | 747 ++ source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h | 950 +-- source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h | 34 +- source/Plugins/SymbolFile/DWARF/NameToDIE.cpp | 34 +- source/Plugins/SymbolFile/DWARF/NameToDIE.h | 33 +- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 8374 ++++++------------- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 807 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 212 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.h | 45 +- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 131 + .../Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h | 70 + .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 49 +- .../Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h | 35 +- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 83 +- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.h | 129 +- .../Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp | 8 +- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h | 31 +- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 56 +- .../InstEmulation/UnwindAssemblyInstEmulation.h | 100 +- .../UnwindAssembly/x86/UnwindAssembly-x86.h | 51 +- source/Symbol/ArmUnwindInfo.cpp | 445 + source/Symbol/Block.cpp | 33 +- source/Symbol/ClangASTContext.cpp | 8480 +++++++++++++++++++- source/Symbol/ClangASTImporter.cpp | 130 +- source/Symbol/ClangASTType.cpp | 7057 ---------------- source/Symbol/ClangExternalASTSourceCallbacks.cpp | 14 + source/Symbol/ClangNamespaceDecl.cpp | 25 - source/Symbol/CompactUnwindInfo.cpp | 10 +- source/Symbol/CompileUnit.cpp | 55 +- source/Symbol/CompilerDecl.cpp | 76 + source/Symbol/CompilerDeclContext.cpp | 75 + source/Symbol/CompilerType.cpp | 1320 +++ source/Symbol/DWARFCallFrameInfo.cpp | 6 +- source/Symbol/DebugMacros.cpp | 65 + source/Symbol/FuncUnwinders.cpp | 43 +- source/Symbol/Function.cpp | 78 +- source/Symbol/GoASTContext.cpp | 1519 ++++ source/Symbol/LineEntry.cpp | 39 + source/Symbol/LineTable.cpp | 14 +- source/Symbol/ObjectFile.cpp | 50 +- source/Symbol/SymbolContext.cpp | 175 +- source/Symbol/SymbolFile.cpp | 69 +- source/Symbol/SymbolVendor.cpp | 51 +- source/Symbol/Symtab.cpp | 10 +- source/Symbol/Type.cpp | 370 +- source/Symbol/TypeList.cpp | 73 +- source/Symbol/TypeMap.cpp | 322 + source/Symbol/TypeSystem.cpp | 255 + source/Symbol/UnwindTable.cpp | 36 +- source/Symbol/Variable.cpp | 106 +- source/Symbol/VariableList.cpp | 18 +- source/Target/ABI.cpp | 19 +- source/Target/CPPLanguageRuntime.cpp | 372 - source/Target/ExecutionContext.cpp | 2 +- source/Target/Language.cpp | 458 ++ source/Target/LanguageRuntime.cpp | 144 +- source/Target/Memory.cpp | 26 +- source/Target/ObjCLanguageRuntime.cpp | 299 +- source/Target/Platform.cpp | 167 +- source/Target/Process.cpp | 1033 ++- source/Target/ProcessLaunchInfo.cpp | 3 +- source/Target/RegisterContext.cpp | 30 +- source/Target/StackFrame.cpp | 86 +- source/Target/StackFrameList.cpp | 14 +- source/Target/StopInfo.cpp | 237 +- source/Target/Target.cpp | 1088 ++- source/Target/TargetList.cpp | 63 +- source/Target/Thread.cpp | 323 +- source/Target/ThreadList.cpp | 38 +- source/Target/ThreadPlan.cpp | 38 +- source/Target/ThreadPlanCallFunction.cpp | 32 +- source/Target/ThreadPlanCallFunctionUsingABI.cpp | 13 +- source/Target/ThreadPlanCallUserExpression.cpp | 6 +- source/Target/ThreadPlanRunToAddress.cpp | 7 +- source/Target/ThreadPlanShouldStopHere.cpp | 40 +- source/Target/ThreadPlanStepInRange.cpp | 62 +- source/Target/ThreadPlanStepInstruction.cpp | 30 +- source/Target/ThreadPlanStepOut.cpp | 79 +- source/Target/ThreadPlanStepOverRange.cpp | 69 +- source/Target/ThreadPlanStepRange.cpp | 65 +- source/Target/ThreadPlanStepThrough.cpp | 14 +- source/Target/ThreadPlanStepUntil.cpp | 211 +- source/Target/ThreadPlanTracer.cpp | 63 +- source/Target/ThreadSpec.cpp | 24 +- source/Target/UnixSignals.cpp | 95 +- source/Utility/ARM64_GCC_Registers.h | 92 - source/Utility/ARM64_ehframe_Registers.h | 95 + source/Utility/ARM_GCC_Registers.h | 146 - source/Utility/ARM_ehframe_Registers.h | 38 + source/Utility/ConvertEnum.cpp | 12 + source/Utility/JSON.cpp | 89 +- source/Utility/ModuleCache.cpp | 186 +- source/Utility/ModuleCache.h | 9 +- source/Utility/SharingPtr.cpp | 2 +- source/Utility/StringExtractor.cpp | 17 +- source/Utility/StringExtractorGDBRemote.cpp | 20 +- source/Utility/StringExtractorGDBRemote.h | 4 + source/Utility/TaskPool.cpp | 88 + source/Utility/UriParser.cpp | 88 +- source/Utility/UriParser.h | 12 +- source/lldb.cpp | 2 +- tools/argdumper/argdumper.exports | 0 tools/argdumper/exports | 0 tools/driver/Driver.cpp | 217 +- tools/driver/Driver.h | 3 + tools/lldb-mi/MICmdArgContext.cpp | 24 +- tools/lldb-mi/MICmdArgContext.h | 17 +- tools/lldb-mi/MICmdArgSet.cpp | 46 +- tools/lldb-mi/MICmdArgSet.h | 47 +- tools/lldb-mi/MICmdArgValBase.cpp | 30 +- tools/lldb-mi/MICmdArgValBase.h | 66 +- tools/lldb-mi/MICmdArgValConsume.cpp | 14 +- tools/lldb-mi/MICmdArgValConsume.h | 11 +- tools/lldb-mi/MICmdArgValFile.cpp | 14 +- tools/lldb-mi/MICmdArgValFile.h | 7 +- tools/lldb-mi/MICmdArgValListBase.cpp | 6 +- tools/lldb-mi/MICmdArgValListBase.h | 9 +- tools/lldb-mi/MICmdArgValListOfN.cpp | 6 +- tools/lldb-mi/MICmdArgValListOfN.h | 9 +- tools/lldb-mi/MICmdArgValNumber.cpp | 6 +- tools/lldb-mi/MICmdArgValNumber.h | 9 +- tools/lldb-mi/MICmdArgValOptionLong.cpp | 18 +- tools/lldb-mi/MICmdArgValOptionLong.h | 11 +- tools/lldb-mi/MICmdArgValOptionShort.cpp | 6 +- tools/lldb-mi/MICmdArgValOptionShort.h | 7 +- tools/lldb-mi/MICmdArgValPrintValues.cpp | 6 +- tools/lldb-mi/MICmdArgValPrintValues.h | 6 +- tools/lldb-mi/MICmdArgValString.cpp | 8 +- tools/lldb-mi/MICmdArgValString.h | 7 +- tools/lldb-mi/MICmdArgValThreadGrp.cpp | 12 +- tools/lldb-mi/MICmdArgValThreadGrp.h | 9 +- tools/lldb-mi/MICmdBase.cpp | 59 +- tools/lldb-mi/MICmdBase.h | 56 +- tools/lldb-mi/MICmdCmd.cpp | 20 +- tools/lldb-mi/MICmdCmd.h | 26 +- tools/lldb-mi/MICmdCmdBreak.cpp | 211 +- tools/lldb-mi/MICmdCmdBreak.h | 98 +- tools/lldb-mi/MICmdCmdData.cpp | 406 +- tools/lldb-mi/MICmdCmdData.h | 156 +- tools/lldb-mi/MICmdCmdEnviro.cpp | 16 +- tools/lldb-mi/MICmdCmdEnviro.h | 15 +- tools/lldb-mi/MICmdCmdExec.cpp | 227 +- tools/lldb-mi/MICmdCmdExec.h | 146 +- tools/lldb-mi/MICmdCmdFile.cpp | 31 +- tools/lldb-mi/MICmdCmdFile.h | 18 +- tools/lldb-mi/MICmdCmdGdbInfo.cpp | 20 +- tools/lldb-mi/MICmdCmdGdbInfo.h | 19 +- tools/lldb-mi/MICmdCmdGdbSet.cpp | 24 +- tools/lldb-mi/MICmdCmdGdbSet.h | 16 +- tools/lldb-mi/MICmdCmdGdbShow.cpp | 24 +- tools/lldb-mi/MICmdCmdGdbShow.h | 15 +- tools/lldb-mi/MICmdCmdGdbThread.cpp | 10 +- tools/lldb-mi/MICmdCmdGdbThread.h | 13 +- tools/lldb-mi/MICmdCmdMiscellanous.cpp | 64 +- tools/lldb-mi/MICmdCmdMiscellanous.h | 56 +- tools/lldb-mi/MICmdCmdStack.cpp | 139 +- tools/lldb-mi/MICmdCmdStack.h | 105 +- tools/lldb-mi/MICmdCmdSupportInfo.cpp | 16 +- tools/lldb-mi/MICmdCmdSupportInfo.h | 15 +- tools/lldb-mi/MICmdCmdSupportList.cpp | 19 +- tools/lldb-mi/MICmdCmdSupportList.h | 13 +- tools/lldb-mi/MICmdCmdSymbol.cpp | 136 +- tools/lldb-mi/MICmdCmdSymbol.h | 12 +- tools/lldb-mi/MICmdCmdTarget.cpp | 50 +- tools/lldb-mi/MICmdCmdTarget.h | 39 +- tools/lldb-mi/MICmdCmdThread.cpp | 16 +- tools/lldb-mi/MICmdCmdThread.h | 15 +- tools/lldb-mi/MICmdCmdTrace.cpp | 10 +- tools/lldb-mi/MICmdCmdTrace.h | 13 +- tools/lldb-mi/MICmdCmdVar.cpp | 230 +- tools/lldb-mi/MICmdCmdVar.h | 140 +- tools/lldb-mi/MICmdCommands.cpp | 6 +- tools/lldb-mi/MICmdCommands.h | 5 +- tools/lldb-mi/MICmdData.h | 9 +- tools/lldb-mi/MICmdFactory.cpp | 17 +- tools/lldb-mi/MICmdFactory.h | 19 +- tools/lldb-mi/MICmdInterpreter.cpp | 20 +- tools/lldb-mi/MICmdInterpreter.h | 11 +- tools/lldb-mi/MICmdInvoker.cpp | 32 +- tools/lldb-mi/MICmdInvoker.h | 35 +- tools/lldb-mi/MICmdMgr.cpp | 8 +- tools/lldb-mi/MICmdMgr.h | 11 +- tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp | 4 +- tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h | 12 +- tools/lldb-mi/MICmnBase.cpp | 10 +- tools/lldb-mi/MICmnBase.h | 13 +- tools/lldb-mi/MICmnLLDBBroadcaster.cpp | 8 +- tools/lldb-mi/MICmnLLDBBroadcaster.h | 11 +- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp | 110 +- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h | 17 +- tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp | 30 +- tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h | 31 +- tools/lldb-mi/MICmnLLDBDebugger.cpp | 131 +- tools/lldb-mi/MICmnLLDBDebugger.h | 36 +- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp | 179 +- tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h | 29 +- tools/lldb-mi/MICmnLLDBProxySBValue.h | 3 - tools/lldb-mi/MICmnLLDBUtilSBValue.cpp | 288 +- tools/lldb-mi/MICmnLLDBUtilSBValue.h | 40 +- tools/lldb-mi/MICmnLog.cpp | 16 +- tools/lldb-mi/MICmnLog.h | 29 +- tools/lldb-mi/MICmnLogMediumFile.cpp | 62 +- tools/lldb-mi/MICmnLogMediumFile.h | 33 +- tools/lldb-mi/MICmnMIOutOfBandRecord.cpp | 183 +- tools/lldb-mi/MICmnMIOutOfBandRecord.h | 37 +- tools/lldb-mi/MICmnMIResultRecord.cpp | 103 +- tools/lldb-mi/MICmnMIResultRecord.h | 35 +- tools/lldb-mi/MICmnMIValue.cpp | 8 +- tools/lldb-mi/MICmnMIValue.h | 9 +- tools/lldb-mi/MICmnMIValueConst.cpp | 6 +- tools/lldb-mi/MICmnMIValueConst.h | 8 +- tools/lldb-mi/MICmnMIValueList.cpp | 49 +- tools/lldb-mi/MICmnMIValueList.h | 17 +- tools/lldb-mi/MICmnMIValueResult.cpp | 28 +- tools/lldb-mi/MICmnMIValueResult.h | 13 +- tools/lldb-mi/MICmnMIValueTuple.cpp | 58 +- tools/lldb-mi/MICmnMIValueTuple.h | 21 +- tools/lldb-mi/MICmnResources.cpp | 13 +- tools/lldb-mi/MICmnResources.h | 15 +- tools/lldb-mi/MICmnStreamStderr.cpp | 12 +- tools/lldb-mi/MICmnStreamStderr.h | 15 +- tools/lldb-mi/MICmnStreamStdin.cpp | 14 +- tools/lldb-mi/MICmnStreamStdin.h | 17 +- tools/lldb-mi/MICmnStreamStdout.cpp | 16 +- tools/lldb-mi/MICmnStreamStdout.h | 17 +- tools/lldb-mi/MICmnThreadMgrStd.cpp | 12 +- tools/lldb-mi/MICmnThreadMgrStd.h | 13 +- tools/lldb-mi/MIDataTypes.h | 16 - tools/lldb-mi/MIDriver.cpp | 72 +- tools/lldb-mi/MIDriver.h | 73 +- tools/lldb-mi/MIDriverBase.cpp | 14 +- tools/lldb-mi/MIDriverBase.h | 21 +- tools/lldb-mi/MIDriverMain.cpp | 2 +- tools/lldb-mi/MIDriverMgr.cpp | 38 +- tools/lldb-mi/MIDriverMgr.h | 49 +- tools/lldb-mi/MIExtensions.txt | 9 +- tools/lldb-mi/MIUtilDateTimeStd.cpp | 10 +- tools/lldb-mi/MIUtilDateTimeStd.h | 13 +- tools/lldb-mi/MIUtilDebug.cpp | 10 +- tools/lldb-mi/MIUtilDebug.h | 16 +- tools/lldb-mi/MIUtilFileStd.cpp | 12 +- tools/lldb-mi/MIUtilFileStd.h | 15 +- tools/lldb-mi/MIUtilMapIdToVariant.cpp | 8 +- tools/lldb-mi/MIUtilMapIdToVariant.h | 11 +- tools/lldb-mi/MIUtilParse.cpp | 75 + tools/lldb-mi/MIUtilParse.h | 93 + tools/lldb-mi/MIUtilSingletonBase.h | 14 +- tools/lldb-mi/MIUtilSingletonHelper.h | 7 - tools/lldb-mi/MIUtilString.cpp | 118 +- tools/lldb-mi/MIUtilString.h | 33 +- tools/lldb-mi/MIUtilSystemLinux.cpp | 111 - tools/lldb-mi/MIUtilSystemLinux.h | 45 - tools/lldb-mi/MIUtilSystemOsx.cpp | 111 - tools/lldb-mi/MIUtilSystemOsx.h | 45 - tools/lldb-mi/MIUtilSystemWindows.cpp | 141 - tools/lldb-mi/MIUtilSystemWindows.h | 44 - tools/lldb-mi/MIUtilThreadBaseStd.cpp | 36 +- tools/lldb-mi/MIUtilThreadBaseStd.h | 59 +- tools/lldb-mi/MIUtilVariant.cpp | 18 +- tools/lldb-mi/MIUtilVariant.h | 49 +- tools/lldb-mi/lldb-mi.exports | 0 tools/lldb-server/Acceptor.cpp | 170 + tools/lldb-server/Acceptor.h | 68 + tools/lldb-server/LLDBServerUtilities.cpp | 2 +- tools/lldb-server/exports | 0 tools/lldb-server/lldb-gdbserver.cpp | 158 +- tools/lldb-server/lldb-platform.cpp | 95 +- tools/lldb-server/lldb-server.exports | 0 1134 files changed, 115774 insertions(+), 78628 deletions(-) delete mode 100644 include/lldb/Core/Language.h create mode 100644 include/lldb/Core/ValueObjectConstResultCast.h delete mode 100644 include/lldb/DataFormatters/CXXFormatterFunctions.h create mode 100644 include/lldb/DataFormatters/CXXFunctionPointer.h create mode 100644 include/lldb/DataFormatters/DumpValueObjectOptions.h create mode 100644 include/lldb/DataFormatters/FormattersHelpers.h create mode 100644 include/lldb/DataFormatters/LanguageCategory.h create mode 100644 include/lldb/DataFormatters/VectorIterator.h delete mode 100644 include/lldb/Expression/ASTDumper.h delete mode 100644 include/lldb/Expression/ASTResultSynthesizer.h delete mode 100644 include/lldb/Expression/ASTStructExtractor.h delete mode 100644 include/lldb/Expression/ClangASTSource.h delete mode 100644 include/lldb/Expression/ClangExpression.h delete mode 100644 include/lldb/Expression/ClangExpressionDeclMap.h delete mode 100644 include/lldb/Expression/ClangExpressionParser.h delete mode 100644 include/lldb/Expression/ClangExpressionVariable.h delete mode 100644 include/lldb/Expression/ClangFunction.h delete mode 100644 include/lldb/Expression/ClangModulesDeclVendor.h delete mode 100644 include/lldb/Expression/ClangPersistentVariables.h delete mode 100644 include/lldb/Expression/ClangUserExpression.h delete mode 100644 include/lldb/Expression/ClangUtilityFunction.h create mode 100644 include/lldb/Expression/Expression.h create mode 100644 include/lldb/Expression/ExpressionParser.h create mode 100644 include/lldb/Expression/ExpressionTypeSystemHelper.h create mode 100644 include/lldb/Expression/ExpressionVariable.h create mode 100644 include/lldb/Expression/FunctionCaller.h delete mode 100644 include/lldb/Expression/IRForTarget.h delete mode 100644 include/lldb/Expression/IRToDWARF.h create mode 100644 include/lldb/Expression/LLVMUserExpression.h create mode 100644 include/lldb/Expression/REPL.h create mode 100644 include/lldb/Expression/UserExpression.h create mode 100644 include/lldb/Expression/UtilityFunction.h create mode 100644 include/lldb/Host/common/GetOptInc.h create mode 100644 include/lldb/Host/common/TCPSocket.h create mode 100644 include/lldb/Host/common/UDPSocket.h create mode 100644 include/lldb/Host/netbsd/Config.h create mode 100644 include/lldb/Host/netbsd/HostInfoNetBSD.h create mode 100644 include/lldb/Host/netbsd/HostThreadNetBSD.h create mode 100644 include/lldb/Host/posix/DomainSocket.h delete mode 100644 include/lldb/Interpreter/PythonDataObjects.h delete mode 100644 include/lldb/Interpreter/ScriptInterpreterNone.h delete mode 100644 include/lldb/Interpreter/ScriptInterpreterPython.h create mode 100644 include/lldb/Symbol/ArmUnwindInfo.h delete mode 100644 include/lldb/Symbol/ClangASTType.h delete mode 100644 include/lldb/Symbol/ClangNamespaceDecl.h create mode 100644 include/lldb/Symbol/CompilerDecl.h create mode 100644 include/lldb/Symbol/CompilerDeclContext.h create mode 100644 include/lldb/Symbol/CompilerType.h create mode 100644 include/lldb/Symbol/DebugMacros.h create mode 100644 include/lldb/Symbol/GoASTContext.h create mode 100644 include/lldb/Symbol/TypeMap.h create mode 100644 include/lldb/Symbol/TypeSystem.h create mode 100644 include/lldb/Target/Language.h create mode 100644 include/lldb/Utility/Either.h delete mode 100644 include/lldb/Utility/PythonPointer.h create mode 100644 include/lldb/Utility/TaskPool.h delete mode 100644 include/lldb/lldb-python.h create mode 100644 source/API/liblldb.exports create mode 100644 source/API/liblldb.xcode.exports delete mode 100644 source/Core/Language.cpp create mode 100644 source/Core/ValueObjectConstResultCast.cpp delete mode 100644 source/DataFormatters/CF.cpp delete mode 100644 source/DataFormatters/CXXFormatterFunctions.cpp create mode 100644 source/DataFormatters/CXXFunctionPointer.cpp delete mode 100644 source/DataFormatters/Cocoa.cpp delete mode 100644 source/DataFormatters/CoreMedia.cpp create mode 100644 source/DataFormatters/DumpValueObjectOptions.cpp create mode 100644 source/DataFormatters/FormattersHelpers.cpp create mode 100644 source/DataFormatters/LanguageCategory.cpp delete mode 100644 source/DataFormatters/LibCxx.cpp delete mode 100644 source/DataFormatters/LibCxxInitializerList.cpp delete mode 100644 source/DataFormatters/LibCxxList.cpp delete mode 100644 source/DataFormatters/LibCxxMap.cpp delete mode 100644 source/DataFormatters/LibCxxUnorderedMap.cpp delete mode 100644 source/DataFormatters/LibCxxVector.cpp delete mode 100644 source/DataFormatters/LibStdcpp.cpp delete mode 100644 source/DataFormatters/NSArray.cpp delete mode 100644 source/DataFormatters/NSDictionary.cpp delete mode 100644 source/DataFormatters/NSIndexPath.cpp delete mode 100644 source/DataFormatters/NSSet.cpp delete mode 100644 source/Expression/ASTDumper.cpp delete mode 100644 source/Expression/ASTResultSynthesizer.cpp delete mode 100644 source/Expression/ASTStructExtractor.cpp delete mode 100644 source/Expression/ClangASTSource.cpp delete mode 100644 source/Expression/ClangExpressionDeclMap.cpp delete mode 100644 source/Expression/ClangExpressionParser.cpp delete mode 100644 source/Expression/ClangExpressionVariable.cpp delete mode 100644 source/Expression/ClangFunction.cpp delete mode 100644 source/Expression/ClangModulesDeclVendor.cpp delete mode 100644 source/Expression/ClangPersistentVariables.cpp delete mode 100644 source/Expression/ClangUserExpression.cpp delete mode 100644 source/Expression/ClangUtilityFunction.cpp create mode 100644 source/Expression/Expression.cpp create mode 100644 source/Expression/ExpressionVariable.cpp create mode 100644 source/Expression/FunctionCaller.cpp delete mode 100644 source/Expression/IRForTarget.cpp create mode 100644 source/Expression/LLVMUserExpression.cpp create mode 100644 source/Expression/REPL.cpp create mode 100644 source/Expression/UserExpression.cpp create mode 100644 source/Expression/UtilityFunction.cpp create mode 100644 source/Host/common/GetOptInc.cpp create mode 100644 source/Host/common/TCPSocket.cpp create mode 100644 source/Host/common/UDPSocket.cpp create mode 100644 source/Host/netbsd/Host.cpp create mode 100644 source/Host/netbsd/HostInfoNetBSD.cpp create mode 100644 source/Host/netbsd/HostThreadNetBSD.cpp create mode 100644 source/Host/netbsd/ThisThread.cpp create mode 100644 source/Host/posix/DomainSocket.cpp delete mode 100644 source/Interpreter/PythonDataObjects.cpp delete mode 100644 source/Interpreter/ScriptInterpreterNone.cpp delete mode 100644 source/Interpreter/ScriptInterpreterPython.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTDumper.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTDumper.h create mode 100644 source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h create mode 100644 source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangASTSource.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUserExpression.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h create mode 100644 source/Plugins/ExpressionParser/Clang/IRForTarget.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/IRForTarget.h create mode 100644 source/Plugins/ExpressionParser/Go/GoAST.h create mode 100644 source/Plugins/ExpressionParser/Go/GoLexer.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoLexer.h create mode 100644 source/Plugins/ExpressionParser/Go/GoParser.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoParser.h create mode 100644 source/Plugins/ExpressionParser/Go/GoUserExpression.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoUserExpression.h create mode 100644 source/Plugins/ExpressionParser/Go/gen_go_ast.py create mode 100644 source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp create mode 100644 source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h create mode 100644 source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp create mode 100644 source/Plugins/Language/CPlusPlus/CxxStringTypes.h create mode 100644 source/Plugins/Language/CPlusPlus/LibCxx.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxx.h create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxList.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxMap.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxVector.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibStdcpp.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibStdcpp.h create mode 100644 source/Plugins/Language/Go/GoFormatterFunctions.cpp create mode 100644 source/Plugins/Language/Go/GoFormatterFunctions.h create mode 100644 source/Plugins/Language/Go/GoLanguage.cpp create mode 100644 source/Plugins/Language/Go/GoLanguage.h create mode 100644 source/Plugins/Language/ObjC/CF.cpp create mode 100644 source/Plugins/Language/ObjC/CF.h create mode 100644 source/Plugins/Language/ObjC/Cocoa.cpp create mode 100644 source/Plugins/Language/ObjC/Cocoa.h create mode 100644 source/Plugins/Language/ObjC/CoreMedia.cpp create mode 100644 source/Plugins/Language/ObjC/CoreMedia.h create mode 100644 source/Plugins/Language/ObjC/NSArray.cpp create mode 100644 source/Plugins/Language/ObjC/NSDictionary.cpp create mode 100644 source/Plugins/Language/ObjC/NSDictionary.h create mode 100644 source/Plugins/Language/ObjC/NSError.cpp create mode 100644 source/Plugins/Language/ObjC/NSException.cpp create mode 100644 source/Plugins/Language/ObjC/NSIndexPath.cpp create mode 100644 source/Plugins/Language/ObjC/NSSet.cpp create mode 100644 source/Plugins/Language/ObjC/NSSet.h create mode 100644 source/Plugins/Language/ObjC/NSString.cpp create mode 100644 source/Plugins/Language/ObjC/NSString.h create mode 100644 source/Plugins/Language/ObjC/ObjCLanguage.cpp create mode 100644 source/Plugins/Language/ObjC/ObjCLanguage.h create mode 100644 source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp create mode 100644 source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h create mode 100644 source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp create mode 100644 source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h create mode 100644 source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp create mode 100644 source/Plugins/OperatingSystem/Go/OperatingSystemGo.h create mode 100644 source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp create mode 100644 source/Plugins/Platform/NetBSD/PlatformNetBSD.h delete mode 100644 source/Plugins/Process/FreeBSD/POSIXThread.cpp delete mode 100644 source/Plugins/Process/FreeBSD/POSIXThread.h delete mode 100644 source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp delete mode 100644 source/Plugins/Process/FreeBSD/ProcessPOSIX.h create mode 100644 source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h create mode 100644 source/Plugins/Process/Utility/NetBSDSignals.cpp create mode 100644 source/Plugins/Process/Utility/NetBSDSignals.h delete mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX.h create mode 100644 source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp create mode 100644 source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h create mode 100644 source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h create mode 100644 source/Plugins/ScriptInterpreter/Python/lldb-python.h create mode 100644 source/Plugins/SymbolFile/DWARF/DIERef.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DIERef.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParser.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIE.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.h create mode 100644 source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h create mode 100644 source/Symbol/ArmUnwindInfo.cpp delete mode 100644 source/Symbol/ClangASTType.cpp delete mode 100644 source/Symbol/ClangNamespaceDecl.cpp create mode 100644 source/Symbol/CompilerDecl.cpp create mode 100644 source/Symbol/CompilerDeclContext.cpp create mode 100644 source/Symbol/CompilerType.cpp create mode 100644 source/Symbol/DebugMacros.cpp create mode 100644 source/Symbol/GoASTContext.cpp create mode 100644 source/Symbol/TypeMap.cpp create mode 100644 source/Symbol/TypeSystem.cpp create mode 100644 source/Target/Language.cpp delete mode 100644 source/Utility/ARM64_GCC_Registers.h create mode 100644 source/Utility/ARM64_ehframe_Registers.h delete mode 100644 source/Utility/ARM_GCC_Registers.h create mode 100644 source/Utility/ARM_ehframe_Registers.h create mode 100644 source/Utility/TaskPool.cpp create mode 100644 tools/argdumper/argdumper.exports delete mode 100644 tools/argdumper/exports create mode 100644 tools/lldb-mi/MIUtilParse.cpp create mode 100644 tools/lldb-mi/MIUtilParse.h delete mode 100644 tools/lldb-mi/MIUtilSystemLinux.cpp delete mode 100644 tools/lldb-mi/MIUtilSystemLinux.h delete mode 100644 tools/lldb-mi/MIUtilSystemOsx.cpp delete mode 100644 tools/lldb-mi/MIUtilSystemOsx.h delete mode 100644 tools/lldb-mi/MIUtilSystemWindows.cpp delete mode 100644 tools/lldb-mi/MIUtilSystemWindows.h create mode 100644 tools/lldb-mi/lldb-mi.exports create mode 100644 tools/lldb-server/Acceptor.cpp create mode 100644 tools/lldb-server/Acceptor.h delete mode 100644 tools/lldb-server/exports create mode 100644 tools/lldb-server/lldb-server.exports diff --git a/docs/lldb.1 b/docs/lldb.1 index 0d94dcbe6a78..a28cabe7acc0 100644 --- a/docs/lldb.1 +++ b/docs/lldb.1 @@ -1,19 +1,20 @@ -.Dd June 7, 2012 \" DATE +.Dd December 16, 2015 \" DATE .Dt LLDB 1 \" Program name and manual section number -.Os Darwin \" Operating System -.Sh NAME \" Section Header - required - don't modify +.Os +.Sh NAME \" Section Header - required - do not modify .Nm lldb .Nd The debugger -.Sh SYNOPSIS \" Section Header - required - don't modify +.Sh SYNOPSIS \" Section Header - required - do not modify .Nm lldb .Op Fl hvdexw .Op Fl a Ar arch +.Op Fl c Ar core-file .Op Fl l Ar script-language .Op Fl s Ar lldb-commands .Op Fl n Ar process-name .Op Fl p Ar pid .Ar [[--] ...] -.Sh DESCRIPTION \" Section Header - required - don't modify +.Sh DESCRIPTION \" Section Header - required - do not modify .Nm is the command line interface for the LLDB debugger library. .Nm @@ -24,7 +25,10 @@ The following options are available: .It Fl h, -help Prints out the usage information for the .Nm -debugger. The \fB\-\-help\fR text may be more up-to-date and +debugger. +The +.Fl -help +text may be more up-to-date and authoritative than the command line options described in this man page. .It Fl v, -version @@ -42,9 +46,13 @@ Specifies the executable file that will be launching / attaching to. .It Fl n, -attach-name Ar process-name Specifies the name of a currently-running process to attach to. -(or the name of a process to wait for if \fB\-w\fR is used.) +(or the name of a process to wait for if +.Fl w +is used.) .It Fl w, -wait-for -When used in concert with \&\fB\-n process-name\-E\fR, indicates that +When used in concert with +.Fl n Ar process-name , +indicates that .Nm should wait for a new process of that name to be started -- and attach to it as early in the process-launch as possible. @@ -52,9 +60,12 @@ to it as early in the process-launch as possible. Specifies a currently running process that .Nm should attach to. +.It Fl c, -core Ar core-file +Specifies the core file to examine. .It Fl l, -script-language Ar language Tells the debugger to use the specified scripting language for -user-defined scripts, rather than the default. Valid scripting +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. .It Fl d, -debug @@ -62,8 +73,9 @@ Tells the debugger to print out extra information for debugging itself. .It Fl s, -source Ar filename Tells .Nm -to read in and execute the file "\fBfilename\fR", which -should contain +to read in and execute the file +.Qq Ar filename , +which should contain .Nm commands. .It Fl e, -editor @@ -73,39 +85,62 @@ to open source files using the host's "external editor" mechanism. .It Fl x, -no-lldbinit Do not automatically parse any '.lldbinit' files. .Pp -(If you don't provide -f then the first argument will be the file to be debugged +(If you do not provide -f then the first argument will be the file to +be debugged so 'lldb -- [ []]' also works. -Remember to end the options with "--" if any of your arguments have a "-" in them.) +Remember to end the options with "--" if any of your arguments have +a "-" in them.) .El .Sh USING LLDB In .Nm -there is a \fBhelp\fR command which can be used to find descriptions and examples of -all +there is a +.Cm help +command which can be used to find descriptions and examples of all .Nm -commands. To get help on "\fBbreakpoint set\fR" you would type "\fBhelp breakpoint set\fR". +commands. +To get help on +.Qq Cm breakpoint set +you would type +.Qq Cm help breakpoint set . .Pp -There is also an \fBapropos\fR command which will search the help text of all commands -for a given term -- this is useful for locating a command by topic. For instance, "\fBapropos breakpoint\fR" -will list any command that has the word \fBbreakpoint\fR in its help text. +There is also an +.Cm apropos +command which will search the help text of all commands +for a given term -- this is useful for locating a command by topic. +For instance, +.Qq Cm apropos breakpoint +will list any command that has the word +.Qq Cm breakpoint +in its help text. .Sh FILES .Nm will read settings/aliases/commands from three files at startup, if they exist. .Pp -First, it will read a \fB~/.lldbinit-\fIdebugger\fR command file. If you are using the +First, it will read a +.Pa ~/.lldbinit-debugger +command file. +If you are using the .Nm -command line interface, this is \fB~/.lldbinit-lldb\fR. If you are using +command line interface, this is +.Pa ~/.lldbinit-lldb . +If you are using .Nm inside a GUI debugger like .Nm Xcode -this will be \fB~/.lldbinit-Xcode\fR. This is a useful place to put settings that you -want to apply only when a given +this will be +.Pa ~/.lldbinit-Xcode . +This is a useful place to put settings that you want to apply only when a given .Nm command interpreter is used. .Pp -Second, \fB~/.lldbinit\fR is read. +Second, +.Pa ~/.lldbinit +is read. .Pp -Third, an \fR.lldbinit\fR file in the current working directory (where +Third, an +.Pa .lldbinit +file in the current working directory (where .Nm is started) will be read. .Sh SEE ALSO diff --git a/include/lldb/API/LLDB.h b/include/lldb/API/LLDB.h index 66e095395f13..eed10d08c6cc 100644 --- a/include/lldb/API/LLDB.h +++ b/include/lldb/API/LLDB.h @@ -16,6 +16,7 @@ // Project includes #include "lldb/API/SBDefines.h" #include "lldb/API/SBAddress.h" +#include "lldb/API/SBAttachInfo.h" #include "lldb/API/SBBlock.h" #include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBBreakpointLocation.h" @@ -30,28 +31,47 @@ #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBExecutionContext.h" +#include "lldb/API/SBExpressionOptions.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFileSpecList.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBFunction.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/SBModule.h" +#include "lldb/API/SBModuleSpec.h" +#include "lldb/API/SBPlatform.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBQueue.h" #include "lldb/API/SBQueueItem.h" +#include "lldb/API/SBSection.h" #include "lldb/API/SBSourceManager.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBSymbol.h" #include "lldb/API/SBSymbolContext.h" +#include "lldb/API/SBSymbolContextList.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" +#include "lldb/API/SBThreadCollection.h" +#include "lldb/API/SBThreadPlan.h" #include "lldb/API/SBType.h" +#include "lldb/API/SBTypeCategory.h" +#include "lldb/API/SBTypeEnumMember.h" +#include "lldb/API/SBTypeFilter.h" +#include "lldb/API/SBTypeFormat.h" +#include "lldb/API/SBTypeNameSpecifier.h" +#include "lldb/API/SBTypeSummary.h" +#include "lldb/API/SBTypeSynthetic.h" +#include "lldb/API/SBUnixSignals.h" #include "lldb/API/SBValue.h" #include "lldb/API/SBValueList.h" #include "lldb/API/SBVariablesOptions.h" +#include "lldb/API/SBWatchpoint.h" #endif // LLDB_LLDB_h_ diff --git a/include/lldb/API/SBAttachInfo.h b/include/lldb/API/SBAttachInfo.h index 712150e128be..a246d9919cfa 100644 --- a/include/lldb/API/SBAttachInfo.h +++ b/include/lldb/API/SBAttachInfo.h @@ -23,8 +23,47 @@ public: SBAttachInfo (lldb::pid_t pid); + //------------------------------------------------------------------ + /// Attach to a process by name. + /// + /// This function implies that a future call to SBTarget::Attach(...) + /// will be synchronous. + /// + /// @param[in] path + /// A full or partial name for the process to attach to. + /// + /// @param[in] wait_for + /// If \b false, attach to an existing process whose name matches. + /// If \b true, then wait for the next process whose name matches. + //------------------------------------------------------------------ SBAttachInfo (const char *path, bool wait_for); + //------------------------------------------------------------------ + /// Attach to a process by name. + /// + /// Future calls to SBTarget::Attach(...) will be synchronous or + /// asynchronous depending on the \a async argument. + /// + /// @param[in] path + /// A full or partial name for the process to attach to. + /// + /// @param[in] wait_for + /// If \b false, attach to an existing process whose name matches. + /// If \b true, then wait for the next process whose name matches. + /// + /// @param[in] async + /// If \b false, then the SBTarget::Attach(...) call will be a + /// synchronous call with no way to cancel the attach in + /// progress. + /// If \b true, then the SBTarget::Attach(...) function will + /// return immediately and clients are expected to wait for a + /// process eStateStopped event if a suitable process is + /// eventually found. If the client wants to cancel the event, + /// SBProcess::Stop() can be called and an eStateExited process + /// event will be delivered. + //------------------------------------------------------------------ + SBAttachInfo (const char *path, bool wait_for, bool async); + SBAttachInfo (const SBAttachInfo &rhs); ~SBAttachInfo(); @@ -47,9 +86,45 @@ public: bool GetWaitForLaunch (); + //------------------------------------------------------------------ + /// Set attach by process name settings. + /// + /// Designed to be used after a call to SBAttachInfo::SetExecutable(). + /// This function implies that a call to SBTarget::Attach(...) will + /// be synchronous. + /// + /// @param[in] wait_for + /// If \b false, attach to an existing process whose name matches. + /// If \b true, then wait for the next process whose name matches. + //------------------------------------------------------------------ void SetWaitForLaunch (bool b); + //------------------------------------------------------------------ + /// Set attach by process name settings. + /// + /// Designed to be used after a call to SBAttachInfo::SetExecutable(). + /// Future calls to SBTarget::Attach(...) will be synchronous or + /// asynchronous depending on the \a async argument. + /// + /// @param[in] wait_for + /// If \b false, attach to an existing process whose name matches. + /// If \b true, then wait for the next process whose name matches. + /// + /// @param[in] async + /// If \b false, then the SBTarget::Attach(...) call will be a + /// synchronous call with no way to cancel the attach in + /// progress. + /// If \b true, then the SBTarget::Attach(...) function will + /// return immediately and clients are expected to wait for a + /// process eStateStopped event if a suitable process is + /// eventually found. If the client wants to cancel the event, + /// SBProcess::Stop() can be called and an eStateExited process + /// event will be delivered. + //------------------------------------------------------------------ + void + SetWaitForLaunch (bool b, bool async); + bool GetIgnoreExisting (); diff --git a/include/lldb/API/SBCommandInterpreter.h b/include/lldb/API/SBCommandInterpreter.h index 235a2f3ea603..a8e9bf7ed769 100644 --- a/include/lldb/API/SBCommandInterpreter.h +++ b/include/lldb/API/SBCommandInterpreter.h @@ -10,6 +10,12 @@ #ifndef LLDB_SBCommandInterpreter_h_ #define LLDB_SBCommandInterpreter_h_ +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes #include "lldb/API/SBDefines.h" #include "lldb/API/SBDebugger.h" @@ -59,6 +65,7 @@ public: void SetAddToHistory (bool); + private: lldb_private::CommandInterpreterRunOptions * get () const; @@ -84,11 +91,11 @@ public: SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs); + ~SBCommandInterpreter (); + const lldb::SBCommandInterpreter & operator = (const lldb::SBCommandInterpreter &rhs); - ~SBCommandInterpreter (); - static const char * GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type); @@ -187,7 +194,7 @@ public: lldb::CommandOverrideCallback callback, void *baton); - SBCommandInterpreter (lldb_private::CommandInterpreter *interpreter_ptr = NULL); // Access using SBDebugger::GetCommandInterpreter(); + SBCommandInterpreter(lldb_private::CommandInterpreter *interpreter_ptr = nullptr); // Access using SBDebugger::GetCommandInterpreter(); //---------------------------------------------------------------------- /// Return true if the command interpreter is the active IO handler. @@ -213,7 +220,7 @@ public: /// /// @return /// The string that should be written into the file handle that is - /// feeding the input stream for the debugger, or NULL if there is + /// feeding the input stream for the debugger, or nullptr if there is /// no string for this control key. //---------------------------------------------------------------------- const char * @@ -233,7 +240,6 @@ public: ResolveCommand(const char *command_line, SBCommandReturnObject &result); protected: - lldb_private::CommandInterpreter & ref (); @@ -242,6 +248,7 @@ protected: void reset (lldb_private::CommandInterpreter *); + private: friend class SBDebugger; @@ -254,6 +261,9 @@ private: class SBCommandPluginInterface { public: + virtual + ~SBCommandPluginInterface() = default; + virtual bool DoExecute (lldb::SBDebugger /*debugger*/, char** /*command*/, @@ -261,16 +271,11 @@ public: { return false; } - - virtual - ~SBCommandPluginInterface () - {} }; class SBCommand { public: - SBCommand (); bool @@ -298,13 +303,12 @@ public: SetFlags (uint32_t flags); lldb::SBCommand - AddMultiwordCommand (const char* name, const char* help = NULL); + AddMultiwordCommand(const char* name, const char* help = nullptr); lldb::SBCommand - AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help = NULL); + AddCommand(const char* name, lldb::SBCommandPluginInterface* impl, const char* help = nullptr); private: - friend class SBDebugger; friend class SBCommandInterpreter; diff --git a/include/lldb/API/SBCommandReturnObject.h b/include/lldb/API/SBCommandReturnObject.h index c51d6bc8d2d5..b45eb9c14c04 100644 --- a/include/lldb/API/SBCommandReturnObject.h +++ b/include/lldb/API/SBCommandReturnObject.h @@ -10,8 +10,14 @@ #ifndef LLDB_SBCommandReturnObject_h_ #define LLDB_SBCommandReturnObject_h_ +// C Includes #include +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes #include "lldb/API/SBDefines.h" namespace lldb { @@ -19,22 +25,20 @@ namespace lldb { class LLDB_API SBCommandReturnObject { public: - SBCommandReturnObject (); SBCommandReturnObject (const lldb::SBCommandReturnObject &rhs); + ~SBCommandReturnObject (); + const lldb::SBCommandReturnObject & operator = (const lldb::SBCommandReturnObject &rhs); - SBCommandReturnObject (lldb_private::CommandReturnObject *ptr); lldb_private::CommandReturnObject * Release (); - ~SBCommandReturnObject (); - bool IsValid() const; @@ -99,8 +103,8 @@ public: GetError (bool only_if_no_immediate); void - SetError (lldb::SBError &error, - const char *fallback_error_cstr = NULL); + SetError(lldb::SBError &error, + const char *fallback_error_cstr = nullptr); void SetError (const char* error_cstr); @@ -124,10 +128,10 @@ protected: void SetLLDBObjectPtr (lldb_private::CommandReturnObject *ptr); - private: +private: std::unique_ptr m_opaque_ap; }; } // namespace lldb -#endif // LLDB_SBCommandReturnObject_h_ +#endif // LLDB_SBCommandReturnObject_h_ diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h index 4f2c1d7f8756..7588cfc9ec42 100644 --- a/include/lldb/API/SBDebugger.h +++ b/include/lldb/API/SBDebugger.h @@ -16,13 +16,13 @@ #include "lldb/API/SBPlatform.h" namespace lldb { - class LLDB_API SBInputReader { public: - SBInputReader(); - ~SBInputReader(); + SBInputReader() = default; + ~SBInputReader() = default; + SBError Initialize(lldb::SBDebugger&, unsigned long (*)(void*, lldb::SBInputReader*, lldb::InputReaderAction, char const*, unsigned long), void*, lldb::InputReaderGranularity, char const*, char const*, bool); void SetIsDone(bool); bool IsActive() const; @@ -31,6 +31,16 @@ public: class LLDB_API SBDebugger { public: + SBDebugger(); + + SBDebugger(const lldb::SBDebugger &rhs); + + SBDebugger(const lldb::DebuggerSP &debugger_sp); + + ~SBDebugger(); + + lldb::SBDebugger & + operator = (const lldb::SBDebugger &rhs); static void Initialize(); @@ -54,17 +64,6 @@ public: static void MemoryPressureDetected (); - SBDebugger(); - - SBDebugger(const lldb::SBDebugger &rhs); - - SBDebugger(const lldb::DebuggerSP &debugger_sp); - - lldb::SBDebugger & - operator = (const lldb::SBDebugger &rhs); - - ~SBDebugger(); - bool IsValid() const; @@ -287,6 +286,9 @@ public: SBTypeCategory GetCategory (const char* category_name); + SBTypeCategory + GetCategory (lldb::LanguageType lang_type); + SBTypeCategory CreateCategory (const char* category_name); @@ -329,8 +331,11 @@ public: int &num_errors, bool &quit_requested, bool &stopped_for_crash); -private: + + SBError + RunREPL (lldb::LanguageType language, const char *repl_options); +private: friend class SBCommandInterpreter; friend class SBInputReader; friend class SBListener; @@ -357,7 +362,6 @@ private: }; // class SBDebugger - } // namespace lldb #endif // LLDB_SBDebugger_h_ diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h index 09bea502dd01..d81bba5a2e23 100644 --- a/include/lldb/API/SBDefines.h +++ b/include/lldb/API/SBDefines.h @@ -86,9 +86,7 @@ class LLDB_API SBTypeMemberFunction; class LLDB_API SBTypeNameSpecifier; class LLDB_API SBTypeSummary; class LLDB_API SBTypeSummaryOptions; -#ifndef LLDB_DISABLE_PYTHON class LLDB_API SBTypeSynthetic; -#endif class LLDB_API SBTypeList; class LLDB_API SBValue; class LLDB_API SBValueList; diff --git a/include/lldb/API/SBFunction.h b/include/lldb/API/SBFunction.h index 86cfeb49bb58..f76c77c44e3f 100644 --- a/include/lldb/API/SBFunction.h +++ b/include/lldb/API/SBFunction.h @@ -53,6 +53,9 @@ public: lldb::SBAddress GetEndAddress (); + const char * + GetArgumentName (uint32_t arg_idx); + uint32_t GetPrologueByteSize (); @@ -65,6 +68,9 @@ public: lldb::LanguageType GetLanguage (); + bool + GetIsOptimized (); + bool operator == (const lldb::SBFunction &rhs) const; diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h index 71bca4fc697a..1a9cc8022880 100644 --- a/include/lldb/API/SBProcess.h +++ b/include/lldb/API/SBProcess.h @@ -294,8 +294,56 @@ public: uint32_t GetNumSupportedHardwareWatchpoints (lldb::SBError &error) const; + //------------------------------------------------------------------ + /// Load a shared library into this process. + /// + /// @param[in] remote_image_spec + /// The path for the shared library on the target what you want + /// to load. + /// + /// @param[out] error + /// An error object that gets filled in with any errors that + /// might occur when trying to load the shared library. + /// + /// @return + /// A token that represents the shared library that can be + /// later used to unload the shared library. A value of + /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared + /// library can't be opened. + //------------------------------------------------------------------ uint32_t - LoadImage (lldb::SBFileSpec &image_spec, lldb::SBError &error); + LoadImage (lldb::SBFileSpec &remote_image_spec, lldb::SBError &error); + + //------------------------------------------------------------------ + /// Load a shared library into this process. + /// + /// @param[in] local_image_spec + /// The file spec that points to the shared library that you + /// want to load if the library is located on the host. The + /// library will be copied over to the location specified by + /// remote_image_spec or into the current working directory with + /// the same filename if the remote_image_spec isn't specified. + /// + /// @param[in] remote_image_spec + /// If local_image_spec is specified then the location where the + /// library should be copied over from the host. If + /// local_image_spec isn't specified, then the path for the + /// shared library on the target what you want to load. + /// + /// @param[out] error + /// An error object that gets filled in with any errors that + /// might occur when trying to load the shared library. + /// + /// @return + /// A token that represents the shared library that can be + /// later used to unload the shared library. A value of + /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared + /// library can't be opened. + //------------------------------------------------------------------ + uint32_t + LoadImage (const lldb::SBFileSpec &local_image_spec, + const lldb::SBFileSpec &remote_image_spec, + lldb::SBError &error); lldb::SBError UnloadImage (uint32_t image_token); @@ -341,6 +389,10 @@ public: bool IsInstrumentationRuntimePresent(InstrumentationRuntimeType type); + // Save the state of the process in a core file (or mini dump on Windows). + lldb::SBError + SaveCore(const char *file_name); + protected: friend class SBAddress; friend class SBBreakpoint; diff --git a/include/lldb/API/SBStream.h b/include/lldb/API/SBStream.h index 2b25cd2c68f2..e62723c2f37e 100644 --- a/include/lldb/API/SBStream.h +++ b/include/lldb/API/SBStream.h @@ -21,7 +21,9 @@ class LLDB_API SBStream public: SBStream (); - + + SBStream (SBStream &&rhs); + ~SBStream (); bool diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h index 2ca0b124ce0a..723c433b521a 100644 --- a/include/lldb/API/SBTarget.h +++ b/include/lldb/API/SBTarget.h @@ -10,6 +10,10 @@ #ifndef LLDB_SBTarget_h_ #define LLDB_SBTarget_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/API/SBDefines.h" #include "lldb/API/SBAddress.h" #include "lldb/API/SBAttachInfo.h" @@ -50,14 +54,14 @@ public: SBTarget (const lldb::TargetSP& target_sp); - const lldb::SBTarget& - operator = (const lldb::SBTarget& rhs); - //------------------------------------------------------------------ // Destructor //------------------------------------------------------------------ ~SBTarget(); + const lldb::SBTarget& + operator = (const lldb::SBTarget& rhs); + bool IsValid() const; @@ -135,17 +139,17 @@ public: /// /// @param[in] stdin_path /// The path to use when re-directing the STDIN of the new - /// process. If all stdXX_path arguments are NULL, a pseudo + /// process. If all stdXX_path arguments are nullptr, a pseudo /// terminal will be used. /// /// @param[in] stdout_path /// The path to use when re-directing the STDOUT of the new - /// process. If all stdXX_path arguments are NULL, a pseudo + /// process. If all stdXX_path arguments are nullptr, a pseudo /// terminal will be used. /// /// @param[in] stderr_path /// The path to use when re-directing the STDERR of the new - /// process. If all stdXX_path arguments are NULL, a pseudo + /// process. If all stdXX_path arguments are nullptr, a pseudo /// terminal will be used. /// /// @param[in] working_directory @@ -175,8 +179,10 @@ public: uint32_t launch_flags, // See LaunchFlags bool stop_at_entry, lldb::SBError& error); - - + + SBProcess + LoadCore (const char *core_file); + //------------------------------------------------------------------ /// Launch a new process with sensible defaults. /// @@ -211,9 +217,6 @@ public: SBProcess Launch (SBLaunchInfo &launch_info, SBError& error); - SBProcess - LoadCore (const char *core_file); - SBProcess Attach (SBAttachInfo &attach_info, SBError& error); @@ -248,6 +251,7 @@ public: ::pid_t pid, // 32 bit int process ID lldb::SBError& error); // DEPRECATED #endif + //------------------------------------------------------------------ /// Attach to process with name. /// @@ -288,7 +292,7 @@ public: /// The url to connect to, e.g., 'connect://localhost:12345'. /// /// @param[in] plugin_name - /// The plugin name to be used; can be NULL. + /// The plugin name to be used; can be nullptr. /// /// @param[out] error /// An error explaining what went wrong if the connect fails. @@ -421,7 +425,6 @@ public: lldb::SBError SetModuleLoadAddress (lldb::SBModule module, int64_t sections_offset); - //------------------------------------------------------------------ /// Clear the section base load addresses for all sections in a module. @@ -618,7 +621,7 @@ public: BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line); lldb::SBBreakpoint - BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL); + BreakpointCreateByName(const char *symbol_name, const char *module_name = nullptr); // This version uses name_type_mask = eFunctionNameTypeAuto lldb::SBBreakpoint @@ -632,15 +635,30 @@ public: const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list); + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, + uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + lldb::LanguageType symbol_language, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateByNames (const char *symbol_name[], + uint32_t num_names, + uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + lldb::SBBreakpoint BreakpointCreateByNames (const char *symbol_name[], uint32_t num_names, uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + lldb::LanguageType symbol_language, const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list); lldb::SBBreakpoint - BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL); + BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = nullptr); lldb::SBBreakpoint BreakpointCreateByRegex (const char *symbol_name_regex, @@ -648,9 +666,15 @@ public: const SBFileSpecList &comp_unit_list); lldb::SBBreakpoint - BreakpointCreateBySourceRegex (const char *source_regex, - const SBFileSpec &source_file, - const char *module_name = NULL); + BreakpointCreateByRegex (const char *symbol_name_regex, + lldb::LanguageType symbol_language, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateBySourceRegex(const char *source_regex, + const SBFileSpec &source_file, + const char *module_name = nullptr); lldb::SBBreakpoint BreakpointCreateBySourceRegex (const char *source_regex, @@ -665,6 +689,9 @@ public: lldb::SBBreakpoint BreakpointCreateByAddress (addr_t address); + lldb::SBBreakpoint + BreakpointCreateBySBAddress (SBAddress &address); + uint32_t GetNumBreakpoints () const; @@ -808,15 +835,10 @@ protected: void SetSP (const lldb::TargetSP& target_sp); - private: - //------------------------------------------------------------------ - // For Target only - //------------------------------------------------------------------ - lldb::TargetSP m_opaque_sp; }; } // namespace lldb -#endif // LLDB_SBTarget_h_ +#endif // LLDB_SBTarget_h_ diff --git a/include/lldb/API/SBType.h b/include/lldb/API/SBType.h index 01f0c6afc795..ed3c2ff23863 100644 --- a/include/lldb/API/SBType.h +++ b/include/lldb/API/SBType.h @@ -85,7 +85,13 @@ public: const char * GetName (); - + + const char * + GetDemangledName (); + + const char * + GetMangledName (); + lldb::SBType GetType (); @@ -158,6 +164,9 @@ public: bool IsTypedefType (); + bool + IsAnonymousType (); + lldb::SBType GetPointerType(); @@ -290,7 +299,7 @@ protected: friend class SBTypeList; friend class SBValue; - SBType (const lldb_private::ClangASTType &); + SBType (const lldb_private::CompilerType &); SBType (const lldb::TypeSP &); SBType (const lldb::TypeImplSP &); diff --git a/include/lldb/API/SBTypeCategory.h b/include/lldb/API/SBTypeCategory.h index 30c338b28a46..997b3fc2f98d 100644 --- a/include/lldb/API/SBTypeCategory.h +++ b/include/lldb/API/SBTypeCategory.h @@ -36,6 +36,15 @@ namespace lldb { const char* GetName(); + lldb::LanguageType + GetLanguageAtIndex (uint32_t idx); + + uint32_t + GetNumLanguages (); + + void + AddLanguage (lldb::LanguageType language); + bool GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); diff --git a/include/lldb/API/SBTypeSummary.h b/include/lldb/API/SBTypeSummary.h index 9b367ba5f982..f4c666180085 100644 --- a/include/lldb/API/SBTypeSummary.h +++ b/include/lldb/API/SBTypeSummary.h @@ -12,8 +12,6 @@ #include "lldb/API/SBDefines.h" -#ifndef LLDB_DISABLE_PYTHON - namespace lldb { class LLDB_API SBTypeSummaryOptions { @@ -71,6 +69,9 @@ namespace lldb { public: SBTypeSummary(); + + // Native function summary formatter callback + typedef bool (*FormatCallback) (SBValue, SBTypeSummaryOptions, SBStream&); static SBTypeSummary CreateWithSummaryString (const char* data, @@ -83,6 +84,11 @@ namespace lldb { static SBTypeSummary CreateWithScriptCode (const char* data, uint32_t options = 0); // see lldb::eTypeOption values + + static SBTypeSummary + CreateWithCallback (FormatCallback cb, + uint32_t options = 0, + const char* description = nullptr); SBTypeSummary (const lldb::SBTypeSummary &rhs); @@ -125,6 +131,9 @@ namespace lldb { lldb::SBTypeSummary & operator = (const lldb::SBTypeSummary &rhs); + bool + DoesPrintValue (lldb::SBValue value); + bool IsEqualTo (lldb::SBTypeSummary &rhs); @@ -160,6 +169,4 @@ namespace lldb { } // namespace lldb -#endif // LLDB_DISABLE_PYTHON - #endif // LLDB_SBTypeSummary_h_ diff --git a/include/lldb/API/SBValue.h b/include/lldb/API/SBValue.h index a070b149f34f..a7e015064f96 100644 --- a/include/lldb/API/SBValue.h +++ b/include/lldb/API/SBValue.h @@ -139,10 +139,8 @@ public: lldb::SBTypeFormat GetTypeFormat (); -#ifndef LLDB_DISABLE_PYTHON lldb::SBTypeSummary GetTypeSummary (); -#endif lldb::SBTypeFilter GetTypeFilter (); @@ -206,7 +204,11 @@ public: /// pointer to a 'Point' type, then the child at index zero will be /// the 'x' member, and the child at index 1 will be the 'y' member /// (the child at index zero won't be a 'Point' instance). - /// + /// + /// If you actually need an SBValue that represents the type pointed + /// to by a SBValue for which GetType().IsPointeeType() returns true, + /// regardless of the pointee type, you can do that with SBValue::Dereference. + /// /// Arrays have a preset number of children that can be accessed by /// index and will returns invalid child values for indexes that are /// out of bounds unless the \a synthetic_allowed is \b true. In this @@ -332,6 +334,9 @@ public: uint32_t GetNumChildren (); + uint32_t + GetNumChildren (uint32_t max); + void * GetOpaqueType(); @@ -350,6 +355,7 @@ public: lldb::SBValue Dereference (); + // Deprecated - please use GetType().IsPointerType() instead. bool TypeIsPointerType (); diff --git a/include/lldb/API/SystemInitializerFull.h b/include/lldb/API/SystemInitializerFull.h index 6280fe8aef04..9e37611a6598 100644 --- a/include/lldb/API/SystemInitializerFull.h +++ b/include/lldb/API/SystemInitializerFull.h @@ -26,15 +26,15 @@ class SystemInitializerFull : public SystemInitializerCommon { public: SystemInitializerFull(); - virtual ~SystemInitializerFull(); + ~SystemInitializerFull() override; void Initialize() override; void Terminate() override; private: void InitializeSWIG(); - void TerminateSWIG(); }; -} -#endif +} // namespace lldb_private + +#endif // LLDB_API_SYSTEM_INITIALIZER_FULL_H diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index a70c2787a1ef..7fdf06da3936 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -12,7 +12,10 @@ // C Includes // C++ Includes +#include +#include #include +#include // Other libraries and framework includes // Project includes @@ -81,11 +84,9 @@ class Breakpoint: public Stoppoint { public: - static const ConstString & GetEventIdentifier (); - //------------------------------------------------------------------ /// An enum specifying the match style for breakpoint settings. At /// present only used for function name style breakpoints. @@ -101,18 +102,16 @@ public: public EventData { public: + BreakpointEventData (lldb::BreakpointEventType sub_type, + const lldb::BreakpointSP &new_breakpoint_sp); + + ~BreakpointEventData() override; static const ConstString & GetFlavorString (); - virtual const ConstString & - GetFlavor () const; - - BreakpointEventData (lldb::BreakpointEventType sub_type, - const lldb::BreakpointSP &new_breakpoint_sp); - - virtual - ~BreakpointEventData(); + const ConstString & + GetFlavor() const override; lldb::BreakpointEventType GetBreakpointEventType () const; @@ -126,9 +125,8 @@ public: return m_locations; } - - virtual void - Dump (Stream *s) const; + void + Dump(Stream *s) const override; static lldb::BreakpointEventType GetBreakpointEventTypeFromEvent (const lldb::EventSP &event_sp); @@ -146,7 +144,6 @@ public: GetEventDataFromEvent (const Event *event_sp); private: - lldb::BreakpointEventType m_breakpoint_event; lldb::BreakpointSP m_new_breakpoint_sp; BreakpointLocationCollection m_locations; @@ -154,11 +151,10 @@ public: DISALLOW_COPY_AND_ASSIGN (BreakpointEventData); }; - class BreakpointPrecondition { public: - virtual ~BreakpointPrecondition() {} + virtual ~BreakpointPrecondition() = default; virtual bool EvaluatePrecondition(StoppointCallbackContext &context); @@ -167,7 +163,7 @@ public: ConfigurePrecondition(Args &options); virtual void - DescribePrecondition(Stream &stream, lldb::DescriptionLevel level); + GetDescription(Stream &stream, lldb::DescriptionLevel level); }; typedef std::shared_ptr BreakpointPreconditionSP; @@ -179,7 +175,7 @@ public: /// breakpoints. The varieties of breakpoints are specified instead by /// providing different resolvers & filters. //------------------------------------------------------------------ - ~Breakpoint(); + ~Breakpoint() override; //------------------------------------------------------------------ // Methods @@ -197,14 +193,13 @@ public: /// Standard "Dump" method. At present it does nothing. //------------------------------------------------------------------ void - Dump (Stream *s); + Dump(Stream *s) override; //------------------------------------------------------------------ // The next set of methods provide ways to tell the breakpoint to update // it's location list - usually done when modules appear or disappear. //------------------------------------------------------------------ - //------------------------------------------------------------------ /// Tell this breakpoint to clear all its breakpoint sites. Done /// when the process holding the breakpoint sites is destroyed. @@ -262,7 +257,6 @@ public: bool load_event, bool delete_locations = false); - //------------------------------------------------------------------ /// Tells the breakpoint the old module \a old_module_sp has been /// replaced by new_module_sp (usually because the underlying file has been @@ -294,8 +288,8 @@ public: /// Returns a pointer to the new location. //------------------------------------------------------------------ lldb::BreakpointLocationSP - AddLocation (const Address &addr, - bool *new_location = NULL); + AddLocation(const Address &addr, + bool *new_location = nullptr); //------------------------------------------------------------------ /// Find a breakpoint location by Address. @@ -304,7 +298,7 @@ public: /// The Address specifying the location. /// @return /// Returns a shared pointer to the location at \a addr. The pointer - /// in the shared pointer will be NULL if there is no location at that address. + /// in the shared pointer will be nullptr if there is no location at that address. //------------------------------------------------------------------ lldb::BreakpointLocationSP FindLocationByAddress (const Address &addr); @@ -328,7 +322,7 @@ public: /// The ID specifying the location. /// @return /// Returns a shared pointer to the location with ID \a bp_loc_id. The pointer - /// in the shared pointer will be NULL if there is no location with that ID. + /// in the shared pointer will be nullptr if there is no location with that ID. //------------------------------------------------------------------ lldb::BreakpointLocationSP FindLocationByID (lldb::break_id_t bp_loc_id); @@ -341,7 +335,7 @@ public: /// /// @return /// Returns a shared pointer to the location with index \a - /// index. The shared pointer might contain NULL if \a index is + /// index. The shared pointer might contain nullptr if \a index is /// greater than then number of actual locations. //------------------------------------------------------------------ lldb::BreakpointLocationSP @@ -373,7 +367,7 @@ public: /// If \a enable is \b true, enable the breakpoint, if \b false disable it. //------------------------------------------------------------------ void - SetEnabled (bool enable); + SetEnabled(bool enable) override; //------------------------------------------------------------------ /// Check the Enable/Disable state. @@ -381,7 +375,7 @@ public: /// \b true if the breakpoint is enabled, \b false if disabled. //------------------------------------------------------------------ bool - IsEnabled (); + IsEnabled() override; //------------------------------------------------------------------ /// Set the breakpoint to ignore the next \a count breakpoint hits. @@ -407,7 +401,6 @@ public: uint32_t GetHitCount () const; - //------------------------------------------------------------------ /// If \a one_shot is \b true, breakpoint will be deleted on first hit. //------------------------------------------------------------------ @@ -490,7 +483,7 @@ public: /// /// @param[in] condition /// The condition expression to evaluate when the breakpoint is hit. - /// Pass in NULL to clear the condition. + /// Pass in nullptr to clear the condition. //------------------------------------------------------------------ void SetCondition (const char *condition); @@ -498,7 +491,7 @@ public: /// Return a pointer to the text of the condition expression. /// /// @return - /// A pointer to the condition expression text, or NULL if no + /// A pointer to the condition expression text, or nullptr if no // condition has been set. //------------------------------------------------------------------ const char *GetConditionText () const; @@ -560,7 +553,7 @@ public: /// Return the "kind" description for a breakpoint. /// /// @return - /// The breakpoint kind, or NULL if none is set. + /// The breakpoint kind, or nullptr if none is set. //------------------------------------------------------------------ const char *GetBreakpointKind () const { @@ -619,7 +612,6 @@ public: BreakpointOptions * GetOptions (); - //------------------------------------------------------------------ /// Invoke the callback action when the breakpoint is hit. /// @@ -713,7 +705,6 @@ protected: // Protected Methods //------------------------------------------------------------------ - //------------------------------------------------------------------ /// Constructors and Destructors /// Only the Target can make a breakpoint, and it owns the breakpoint lifespans. @@ -807,4 +798,4 @@ private: } // namespace lldb_private -#endif // liblldb_Breakpoint_h_ +#endif // liblldb_Breakpoint_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index c3e620d085c6..58d144cfb668 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -11,12 +11,10 @@ #define liblldb_BreakpointLocation_h_ // C Includes - // C++ Includes -#include +#include // Other libraries and framework includes - // Project includes #include "lldb/lldb-private.h" #include "lldb/Breakpoint/StoppointLocation.h" @@ -49,7 +47,7 @@ class BreakpointLocation : public StoppointLocation { public: - ~BreakpointLocation (); + ~BreakpointLocation() override; //------------------------------------------------------------------ /// Gets the load address for this breakpoint location @@ -58,7 +56,7 @@ public: /// LLDB_INVALID_ADDRESS if not yet set. //------------------------------------------------------------------ lldb::addr_t - GetLoadAddress () const; + GetLoadAddress() const override; //------------------------------------------------------------------ /// Gets the Address for this breakpoint location @@ -74,6 +72,9 @@ public: //------------------------------------------------------------------ Breakpoint & GetBreakpoint (); + + Target & + GetTarget(); //------------------------------------------------------------------ /// Determines whether we should stop due to a hit at this @@ -88,7 +89,7 @@ public: /// \b false otherwise. //------------------------------------------------------------------ bool - ShouldStop (StoppointCallbackContext *context); + ShouldStop(StoppointCallbackContext *context) override; //------------------------------------------------------------------ // The next section deals with various breakpoint options. @@ -169,16 +170,15 @@ public: /// Return a pointer to the text of the condition expression. /// /// @return - /// A pointer to the condition expression text, or NULL if no + /// A pointer to the condition expression text, or nullptr if no // condition has been set. //------------------------------------------------------------------ const char * - GetConditionText (size_t *hash = NULL) const; + GetConditionText(size_t *hash = nullptr) const; bool ConditionSaysStop (ExecutionContext &exe_ctx, Error &error); - //------------------------------------------------------------------ /// Set the valid thread to be checked when the breakpoint is hit. /// @@ -270,7 +270,7 @@ public: /// Standard "Dump" method. At present it does nothing. //------------------------------------------------------------------ void - Dump (Stream *s) const; + Dump(Stream *s) const override; //------------------------------------------------------------------ /// Use this to set location specific breakpoint options. @@ -299,7 +299,6 @@ public: bool ValidForThisThread (Thread *thread); - //------------------------------------------------------------------ /// Invoke the callback action when the breakpoint is hit. /// @@ -418,7 +417,6 @@ private: void UndoBumpHitCount(); - //------------------------------------------------------------------ // Constructors and Destructors // @@ -459,9 +457,9 @@ private: bool m_is_indirect; Address m_address; ///< The address defining this location. Breakpoint &m_owner; ///< The breakpoint that produced this object. - std::unique_ptr m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options. + std::unique_ptr m_options_ap; ///< Breakpoint options pointer, nullptr if we're using our breakpoint's options. lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.) - lldb::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. + lldb::UserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes. size_t m_condition_hash; ///< For testing whether the condition source code changed. @@ -479,4 +477,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointLocation_h_ +#endif // liblldb_BreakpointLocation_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h index f67ef89ad705..81526089b427 100644 --- a/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/include/lldb/Breakpoint/BreakpointLocationList.h @@ -12,8 +12,9 @@ // C Includes // C++ Includes -#include #include +#include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -56,7 +57,7 @@ public: /// The address to look for. /// /// @result - /// A shared pointer to the breakpoint. May contain a NULL + /// A shared pointer to the breakpoint. May contain a nullptr /// pointer if the breakpoint doesn't exist. //------------------------------------------------------------------ const lldb::BreakpointLocationSP @@ -70,7 +71,7 @@ public: /// The breakpoint location ID to seek for. /// /// @result - /// A shared pointer to the breakpoint. May contain a NULL + /// A shared pointer to the breakpoint. May contain a nullptr /// pointer if the breakpoint doesn't exist. //------------------------------------------------------------------ lldb::BreakpointLocationSP @@ -116,7 +117,7 @@ public: /// The breakpoint location index to seek for. /// /// @result - /// A shared pointer to the breakpoint. May contain a NULL + /// A shared pointer to the breakpoint. May contain a nullptr /// pointer if the breakpoint doesn't exist. //------------------------------------------------------------------ lldb::BreakpointLocationSP @@ -130,7 +131,7 @@ public: /// The breakpoint location index to seek for. /// /// @result - /// A shared pointer to the breakpoint. May contain a NULL + /// A shared pointer to the breakpoint. May contain a nullptr /// pointer if the breakpoint doesn't exist. //------------------------------------------------------------------ const lldb::BreakpointLocationSP @@ -216,7 +217,6 @@ public: lldb::DescriptionLevel level); protected: - //------------------------------------------------------------------ /// This is the standard constructor. /// @@ -246,9 +246,9 @@ protected: StopRecordingNewLocations(); lldb::BreakpointLocationSP - AddLocation (const Address &addr, - bool resolve_indirect_symbols, - bool *new_location = NULL); + AddLocation(const Address &addr, + bool resolve_indirect_symbols, + bool *new_location = nullptr); void SwapLocation (lldb::BreakpointLocationSP to_location_sp, lldb::BreakpointLocationSP from_location_sp); @@ -273,16 +273,17 @@ protected: mutable Mutex m_mutex; lldb::break_id_t m_next_id; BreakpointLocationCollection *m_new_location_recorder; + public: typedef AdaptedIterable BreakpointLocationIterable; + BreakpointLocationIterable BreakpointLocations() { return BreakpointLocationIterable(m_locations); } - }; } // namespace lldb_private -#endif // liblldb_BreakpointLocationList_h_ +#endif // liblldb_BreakpointLocationList_h_ diff --git a/include/lldb/Breakpoint/BreakpointOptions.h b/include/lldb/Breakpoint/BreakpointOptions.h index bf10fc096d75..e7882147a4da 100644 --- a/include/lldb/Breakpoint/BreakpointOptions.h +++ b/include/lldb/Breakpoint/BreakpointOptions.h @@ -12,6 +12,9 @@ // C Includes // C++ Includes +#include +#include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -115,7 +118,6 @@ public: //------------------------------------------------------------------ void SetCallback (BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); - //------------------------------------------------------------------ /// Remove the callback from this option set. //------------------------------------------------------------------ @@ -184,10 +186,10 @@ public: /// Return a pointer to the text of the condition expression. /// /// @return - /// A pointer to the condition expression text, or NULL if no + /// A pointer to the condition expression text, or nullptr if no // condition has been set. //------------------------------------------------------------------ - const char *GetConditionText (size_t *hash = NULL) const; + const char *GetConditionText(size_t *hash = nullptr) const; //------------------------------------------------------------------ // Enabled/Ignore Count @@ -257,10 +259,10 @@ public: } //------------------------------------------------------------------ - /// Return the current thread spec for this option. This will return NULL if the no thread + /// Return the current thread spec for this option. This will return nullptr if the no thread /// specifications have been set for this Option yet. /// @return - /// The thread specification pointer for this option, or NULL if none has + /// The thread specification pointer for this option, or nullptr if none has /// been set yet. //------------------------------------------------------------------ const ThreadSpec * @@ -298,7 +300,6 @@ public: lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - struct CommandData { CommandData () : @@ -308,10 +309,8 @@ public: { } - ~CommandData () - { - } - + ~CommandData() = default; + StringList user_source; std::string script_source; bool stop_on_error; @@ -325,16 +324,14 @@ public: { } - virtual - ~CommandBaton () + ~CommandBaton() override { delete ((CommandData *)m_data); - m_data = NULL; + m_data = nullptr; } - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level) const; - + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const override; }; protected: @@ -359,4 +356,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointOptions_h_ +#endif // liblldb_BreakpointOptions_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h index 6ba53ea92f36..198abed841b2 100644 --- a/include/lldb/Breakpoint/BreakpointResolver.h +++ b/include/lldb/Breakpoint/BreakpointResolver.h @@ -66,8 +66,7 @@ public: /// The Destructor is virtual, all significant breakpoint resolvers derive /// from this class. //------------------------------------------------------------------ - virtual - ~BreakpointResolver (); + ~BreakpointResolver() override; //------------------------------------------------------------------ /// This sets the breakpoint for this resolver. @@ -105,8 +104,8 @@ public: /// @param[in] s /// Stream to which the output is copied. //------------------------------------------------------------------ - virtual void - GetDescription (Stream *s) = 0; + void + GetDescription(Stream *s) override = 0; //------------------------------------------------------------------ /// Standard "Dump" method. At present it does nothing. @@ -157,4 +156,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointResolver_h_ +#endif // liblldb_BreakpointResolver_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverAddress.h b/include/lldb/Breakpoint/BreakpointResolverAddress.h index c8f034d7345b..8ec1e39e52ab 100644 --- a/include/lldb/Breakpoint/BreakpointResolverAddress.h +++ b/include/lldb/Breakpoint/BreakpointResolverAddress.h @@ -15,6 +15,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Core/ModuleSpec.h" namespace lldb_private { @@ -31,8 +32,11 @@ public: BreakpointResolverAddress (Breakpoint *bkpt, const Address &addr); - virtual - ~BreakpointResolverAddress (); + BreakpointResolverAddress (Breakpoint *bkpt, + const Address &addr, + const FileSpec &module_spec); + + ~BreakpointResolverAddress() override; void ResolveBreakpoint (SearchFilter &filter) override; @@ -66,12 +70,15 @@ public: CopyForBreakpoint (Breakpoint &breakpoint) override; protected: - Address m_addr; - + Address m_addr; // The address - may be Section Offset or may be just an offset + lldb::addr_t m_resolved_addr; // The current value of the resolved load address for this breakpoint, + FileSpec m_module_filespec; // If this filespec is Valid, and m_addr is an offset, then it will be converted + // to a Section+Offset address in this module, whenever that module gets around to + // being loaded. private: DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress); }; } // namespace lldb_private -#endif // liblldb_BreakpointResolverAddress_h_ +#endif // liblldb_BreakpointResolverAddress_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h index 2403d24515a7..2dde1546f126 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -35,8 +35,7 @@ public: bool skip_prologue, bool exact_match); - virtual - ~BreakpointResolverFileLine (); + ~BreakpointResolverFileLine() override; Searcher::CallbackReturn SearchCallback (SearchFilter &filter, @@ -76,4 +75,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointResolverFileLine_h_ +#endif // liblldb_BreakpointResolverFileLine_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h index 8e18fff16447..a8d7a50b5d93 100644 --- a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h +++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -32,8 +32,7 @@ public: RegularExpression ®ex, bool exact_match); - virtual - ~BreakpointResolverFileRegex (); + ~BreakpointResolverFileRegex() override; Searcher::CallbackReturn SearchCallback (SearchFilter &filter, @@ -70,4 +69,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointResolverFileRegex_h_ +#endif // liblldb_BreakpointResolverFileRegex_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h index c2a5b180f289..aaae9c1a12cf 100644 --- a/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/include/lldb/Breakpoint/BreakpointResolverName.h @@ -14,6 +14,7 @@ // C++ Includes #include #include + // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointResolver.h" @@ -34,6 +35,7 @@ public: BreakpointResolverName (Breakpoint *bkpt, const char *name, uint32_t name_type_mask, + lldb::LanguageType language, Breakpoint::MatchType type, bool skip_prologue); @@ -42,17 +44,20 @@ public: const char *names[], size_t num_names, uint32_t name_type_mask, + lldb::LanguageType language, bool skip_prologue); // This one takes a C++ array of names. It is always MatchType = Exact. BreakpointResolverName (Breakpoint *bkpt, std::vector names, uint32_t name_type_mask, + lldb::LanguageType language, bool skip_prologue); // Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex. BreakpointResolverName (Breakpoint *bkpt, RegularExpression &func_regex, + lldb::LanguageType language, bool skip_prologue); BreakpointResolverName (Breakpoint *bkpt, @@ -61,8 +66,7 @@ public: Breakpoint::MatchType type, bool skip_prologue); - virtual - ~BreakpointResolverName (); + ~BreakpointResolverName() override; Searcher::CallbackReturn SearchCallback (SearchFilter &filter, @@ -114,6 +118,7 @@ protected: ConstString m_class_name; RegularExpression m_regex; Breakpoint::MatchType m_match_type; + lldb::LanguageType m_language; bool m_skip_prologue; void @@ -122,4 +127,4 @@ protected: } // namespace lldb_private -#endif // liblldb_BreakpointResolverName_h_ +#endif // liblldb_BreakpointResolverName_h_ diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h index d67fc8bb57f1..6cebcab8e2db 100644 --- a/include/lldb/Breakpoint/BreakpointSite.h +++ b/include/lldb/Breakpoint/BreakpointSite.h @@ -55,7 +55,7 @@ public: // display any breakpoint opcodes. }; - virtual ~BreakpointSite (); + ~BreakpointSite() override; //---------------------------------------------------------------------- // This section manages the breakpoint traps @@ -139,8 +139,8 @@ public: /// @return /// \b true if we should stop, \b false otherwise. //------------------------------------------------------------------ - virtual bool - ShouldStop (StoppointCallbackContext *context); + bool + ShouldStop(StoppointCallbackContext *context) override; //------------------------------------------------------------------ /// Standard Dump method @@ -149,7 +149,7 @@ public: /// The stream to dump this output. //------------------------------------------------------------------ void - Dump (Stream *s) const; + Dump(Stream *s) const override; //------------------------------------------------------------------ /// The "Owners" are the breakpoint locations that share this @@ -186,6 +186,20 @@ public: lldb::BreakpointLocationSP GetOwnerAtIndex (size_t idx); + //------------------------------------------------------------------ + /// This method copies the breakpoint site's owners into a new collection. + /// It does this while the owners mutex is locked. + /// + /// @param[out] out_collection + /// The BreakpointLocationCollection into which to put the owners + /// of this breakpoint site. + /// + /// @return + /// The number of elements copied into out_collection. + //------------------------------------------------------------------ + size_t + CopyOwnersList (BreakpointLocationCollection &out_collection); + //------------------------------------------------------------------ /// Check whether the owners of this breakpoint site have any /// thread specifiers, and if yes, is \a thread contained in any @@ -201,7 +215,6 @@ public: bool ValidForThisThread (Thread *thread); - //------------------------------------------------------------------ /// Print a description of this breakpoint site to the stream \a s. /// GetDescription tells you about the breakpoint site's owners. @@ -301,4 +314,4 @@ private: } // namespace lldb_private -#endif // liblldb_BreakpointSite_h_ +#endif // liblldb_BreakpointSite_h_ diff --git a/include/lldb/Breakpoint/Watchpoint.h b/include/lldb/Breakpoint/Watchpoint.h index 926e0b506f31..34df24a92c06 100644 --- a/include/lldb/Breakpoint/Watchpoint.h +++ b/include/lldb/Breakpoint/Watchpoint.h @@ -11,19 +11,17 @@ #define liblldb_Watchpoint_h_ // C Includes - // C++ Includes -#include +#include #include // Other libraries and framework includes - // Project includes #include "lldb/lldb-private.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Breakpoint/StoppointLocation.h" #include "lldb/Core/UserID.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" namespace lldb_private { @@ -33,23 +31,20 @@ class Watchpoint : public StoppointLocation { public: - class WatchpointEventData : public EventData { public: + WatchpointEventData (lldb::WatchpointEventType sub_type, + const lldb::WatchpointSP &new_watchpoint_sp); + + ~WatchpointEventData() override; static const ConstString & GetFlavorString (); - virtual const ConstString & - GetFlavor () const; - - WatchpointEventData (lldb::WatchpointEventType sub_type, - const lldb::WatchpointSP &new_watchpoint_sp); - - virtual - ~WatchpointEventData(); + const ConstString & + GetFlavor() const override; lldb::WatchpointEventType GetWatchpointEventType () const; @@ -57,8 +52,8 @@ public: lldb::WatchpointSP & GetWatchpoint (); - virtual void - Dump (Stream *s) const; + void + Dump(Stream *s) const override; static lldb::WatchpointEventType GetWatchpointEventTypeFromEvent (const lldb::EventSP &event_sp); @@ -70,15 +65,15 @@ public: GetEventDataFromEvent (const Event *event_sp); private: - lldb::WatchpointEventType m_watchpoint_event; lldb::WatchpointSP m_new_watchpoint_sp; DISALLOW_COPY_AND_ASSIGN (WatchpointEventData); }; - Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware = true); - ~Watchpoint (); + Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware = true); + + ~Watchpoint() override; void IncrementFalseAlarmsAndReviseHitCount(); @@ -89,11 +84,11 @@ public: void SetEnabled (bool enabled, bool notify = true); - virtual bool - IsHardware () const; + bool + IsHardware() const override; - virtual bool - ShouldStop (StoppointCallbackContext *context); + bool + ShouldStop(StoppointCallbackContext *context) override; bool WatchpointRead () const; bool WatchpointWrite () const; @@ -110,8 +105,8 @@ public: bool CaptureWatchedValue (const ExecutionContext &exe_ctx); void GetDescription (Stream *s, lldb::DescriptionLevel level); - void Dump (Stream *s) const; - void DumpSnapshots (Stream *s, const char * prefix = NULL) const; + void Dump (Stream *s) const override; + void DumpSnapshots(Stream *s, const char *prefix = nullptr) const; void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const; Target &GetTarget() { return m_target; } const Error &GetError() { return m_error; } @@ -173,7 +168,7 @@ public: /// /// @param[in] condition /// The condition expression to evaluate when the watchpoint is hit. - /// Pass in NULL to clear the condition. + /// Pass in nullptr to clear the condition. //------------------------------------------------------------------ void SetCondition (const char *condition); @@ -181,7 +176,7 @@ public: /// Return a pointer to the text of the condition expression. /// /// @return - /// A pointer to the condition expression text, or NULL if no + /// A pointer to the condition expression text, or nullptr if no // condition has been set. //------------------------------------------------------------------ const char *GetConditionText () const; @@ -195,13 +190,12 @@ public: bool IsDisabledDuringEphemeralMode(); - const ClangASTType & - GetClangASTType() + const CompilerType & + GetCompilerType() { return m_type; } - private: friend class Target; friend class WatchpointList; @@ -240,13 +234,13 @@ private: std::string m_watch_spec_str; // Spec for the watchpoint. lldb::ValueObjectSP m_old_value_sp; lldb::ValueObjectSP m_new_value_sp; - ClangASTType m_type; + CompilerType m_type; Error m_error; // An error object describing errors associated with this watchpoint. WatchpointOptions m_options; // Settable watchpoint options, which is a delegate to handle // the callback machinery. bool m_being_created; - std::unique_ptr m_condition_ap; // The condition to test. + std::unique_ptr m_condition_ap; // The condition to test. void SetID(lldb::watch_id_t id) { m_loc_id = id; } @@ -261,4 +255,4 @@ private: } // namespace lldb_private -#endif // liblldb_Watchpoint_h_ +#endif // liblldb_Watchpoint_h_ diff --git a/include/lldb/Breakpoint/WatchpointOptions.h b/include/lldb/Breakpoint/WatchpointOptions.h index 64c65f92b44f..eb08bb32e6ce 100644 --- a/include/lldb/Breakpoint/WatchpointOptions.h +++ b/include/lldb/Breakpoint/WatchpointOptions.h @@ -12,6 +12,9 @@ // C Includes // C++ Includes +#include +#include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -99,7 +102,6 @@ public: //------------------------------------------------------------------ void SetCallback (WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); - //------------------------------------------------------------------ /// Remove the callback from this option set. //------------------------------------------------------------------ @@ -150,10 +152,10 @@ public: const Baton *GetBaton () const; //------------------------------------------------------------------ - /// Return the current thread spec for this option. This will return NULL if the no thread + /// Return the current thread spec for this option. This will return nullptr if the no thread /// specifications have been set for this Option yet. /// @return - /// The thread specification pointer for this option, or NULL if none has + /// The thread specification pointer for this option, or nullptr if none has /// been set yet. //------------------------------------------------------------------ const ThreadSpec * @@ -196,7 +198,6 @@ public: StoppointCallbackContext *context, lldb::user_id_t watch_id); - struct CommandData { CommandData () : @@ -206,10 +207,8 @@ public: { } - ~CommandData () - { - } - + ~CommandData() = default; + StringList user_source; std::string script_source; bool stop_on_error; @@ -223,16 +222,14 @@ public: { } - virtual - ~CommandBaton () + ~CommandBaton() override { delete ((CommandData *)m_data); - m_data = NULL; + m_data = nullptr; } - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level) const; - + void + GetDescription(Stream *s, lldb::DescriptionLevel level) const override; }; protected: @@ -252,4 +249,4 @@ private: } // namespace lldb_private -#endif // liblldb_WatchpointOptions_h_ +#endif // liblldb_WatchpointOptions_h_ diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h index cfa16c30bedb..0afe55b12be3 100644 --- a/include/lldb/Core/Address.h +++ b/include/lldb/Core/Address.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -108,7 +109,6 @@ public: { } - //------------------------------------------------------------------ /// Copy constructor /// @@ -176,6 +176,7 @@ public: const Address& operator= (const Address& rhs); #endif + //------------------------------------------------------------------ /// Clear the object's state. /// @@ -216,7 +217,7 @@ public: class ModulePointerAndOffsetLessThanFunctionObject { public: - ModulePointerAndOffsetLessThanFunctionObject () {} + ModulePointerAndOffsetLessThanFunctionObject() = default; bool operator() (const Address& a, const Address& b) const @@ -326,7 +327,8 @@ public: /// not loaded. //------------------------------------------------------------------ lldb::addr_t - GetOpcodeLoadAddress (Target *target) const; + GetOpcodeLoadAddress (Target *target, + lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; //------------------------------------------------------------------ /// Get the section relative offset value. @@ -354,7 +356,7 @@ public: bool IsSectionOffset() const { - return IsValid() && (GetSection().get() != NULL); + return IsValid() && (GetSection().get() != nullptr); } //------------------------------------------------------------------ @@ -374,7 +376,6 @@ public: return m_offset != LLDB_INVALID_ADDRESS; } - //------------------------------------------------------------------ /// Get the memory cost of this object. /// @@ -425,7 +426,9 @@ public: SetLoadAddress (lldb::addr_t load_addr, Target *target); bool - SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target); + SetOpcodeLoadAddress (lldb::addr_t load_addr, + Target *target, + lldb::AddressClass addr_class = lldb::eAddressClassInvalid); bool SetCallableLoadAddress (lldb::addr_t load_addr, Target *target); @@ -505,6 +508,7 @@ public: { m_section_wp.reset(); } + //------------------------------------------------------------------ /// Reconstruct a symbol context from an address. /// @@ -564,10 +568,8 @@ protected: //------------------------------------------------------------------ bool SectionWasDeletedPrivate() const; - }; - //---------------------------------------------------------------------- // NOTE: Be careful using this operator. It can correctly compare two // addresses from the same Module correctly. It can't compare two @@ -584,12 +586,9 @@ protected: //---------------------------------------------------------------------- bool operator< (const Address& lhs, const Address& rhs); bool operator> (const Address& lhs, const Address& rhs); - - - bool operator== (const Address& lhs, const Address& rhs); bool operator!= (const Address& lhs, const Address& rhs); } // namespace lldb_private -#endif // liblldb_Address_h_ +#endif // liblldb_Address_h_ diff --git a/include/lldb/Core/AddressRange.h b/include/lldb/Core/AddressRange.h index 9d781f3e85ae..31e3286cb110 100644 --- a/include/lldb/Core/AddressRange.h +++ b/include/lldb/Core/AddressRange.h @@ -10,6 +10,10 @@ #ifndef liblldb_AddressRange_h_ #define liblldb_AddressRange_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Core/Address.h" namespace lldb_private { @@ -62,7 +66,7 @@ public: /// @param[in] section_list /// A list of sections, one of which may contain the \a vaddr. //------------------------------------------------------------------ - AddressRange (lldb::addr_t file_addr, lldb::addr_t byte_size, const SectionList *section_list = NULL); + AddressRange(lldb::addr_t file_addr, lldb::addr_t byte_size, const SectionList *section_list = nullptr); //------------------------------------------------------------------ /// Construct with a Address object address and byte size. @@ -281,4 +285,4 @@ protected: } // namespace lldb_private -#endif // liblldb_AddressRange_h_ +#endif // liblldb_AddressRange_h_ diff --git a/include/lldb/Core/AddressResolver.h b/include/lldb/Core/AddressResolver.h index e5fe276e3fb1..711cc57c14a4 100644 --- a/include/lldb/Core/AddressResolver.h +++ b/include/lldb/Core/AddressResolver.h @@ -54,8 +54,7 @@ public: AddressResolver (); - virtual - ~AddressResolver (); + ~AddressResolver () override; virtual void ResolveAddress (SearchFilter &filter); @@ -64,8 +63,8 @@ public: ResolveAddressInModules (SearchFilter &filter, ModuleList &modules); - virtual void - GetDescription (Stream *s) = 0; + void + GetDescription (Stream *s) override = 0; std::vector & GetAddressRanges (); @@ -86,4 +85,4 @@ private: } // namespace lldb_private -#endif // liblldb_AddressResolver_h_ +#endif // liblldb_AddressResolver_h_ diff --git a/include/lldb/Core/AddressResolverFileLine.h b/include/lldb/Core/AddressResolverFileLine.h index ddeb0e0301d2..5b47379ed18e 100644 --- a/include/lldb/Core/AddressResolverFileLine.h +++ b/include/lldb/Core/AddressResolverFileLine.h @@ -30,20 +30,19 @@ public: uint32_t line_no, bool check_inlines); - virtual - ~AddressResolverFileLine (); + ~AddressResolverFileLine () override; - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; protected: FileSpec m_file_spec; // This is the file spec we are looking for. @@ -56,4 +55,4 @@ private: } // namespace lldb_private -#endif // liblldb_AddressResolverFileLine_h_ +#endif // liblldb_AddressResolverFileLine_h_ diff --git a/include/lldb/Core/AddressResolverName.h b/include/lldb/Core/AddressResolverName.h index afde675a89bb..cf792f5054e6 100644 --- a/include/lldb/Core/AddressResolverName.h +++ b/include/lldb/Core/AddressResolverName.h @@ -38,20 +38,19 @@ public: const char *method, AddressResolver::MatchType type); - virtual - ~AddressResolverName (); + ~AddressResolverName () override; - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; protected: ConstString m_func_name; @@ -65,4 +64,4 @@ private: } // namespace lldb_private -#endif // liblldb_AddressResolverName_h_ +#endif // liblldb_AddressResolverName_h_ diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 0b818a0c7123..13ff436cf08f 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -65,7 +65,11 @@ public: eMIPSAse_mips16 = 0x00000400, // MIPS16 ASE eMIPSAse_micromips = 0x00000800, // MICROMIPS ASE eMIPSAse_xpa = 0x00001000, // XPA ASE - eMIPSAse_mask = 0x00001fff + eMIPSAse_mask = 0x00001fff, + eMIPSABI_O32 = 0x00002000, + eMIPSABI_N32 = 0x00004000, + eMIPSABI_N64 = 0x00008000, + eMIPSABI_mask = 0x000ff000 }; enum Core @@ -208,7 +212,11 @@ public: kCore_mips64_last = eCore_mips64r6, kCore_mips64el_first = eCore_mips64el, - kCore_mips64el_last = eCore_mips64r6el + kCore_mips64el_last = eCore_mips64r6el, + + kCore_mips_first = eCore_mips32, + kCore_mips_last = eCore_mips64r6el + }; typedef void (* StopInfoOverrideCallbackType)(lldb_private::Thread &thread); @@ -336,11 +344,29 @@ public: return !m_triple.getVendorName().empty(); } + bool + TripleVendorIsUnspecifiedUnknown() const + { + return m_triple.getVendor() == llvm::Triple::UnknownVendor && m_triple.getVendorName().empty(); + } + bool TripleOSWasSpecified() const { return !m_triple.getOSName().empty(); } + + bool + TripleEnvironmentWasSpecified () const + { + return !m_triple.getEnvironmentName().empty(); + } + + bool + TripleOSIsUnspecifiedUnknown() const + { + return m_triple.getOS() == llvm::Triple::UnknownOS && m_triple.getOSName().empty(); + } //------------------------------------------------------------------ /// Merges fields from another ArchSpec into this ArchSpec. @@ -480,6 +506,9 @@ public: return m_triple; } + void + DumpTriple(Stream &s) const; + //------------------------------------------------------------------ /// Architecture tripple setter. /// @@ -564,7 +593,18 @@ public: //------------------------------------------------------------------ StopInfoOverrideCallbackType GetStopInfoOverrideCallback () const; + + bool + IsFullySpecifiedTriple () const; + void + PiecewiseTripleCompare (const ArchSpec &other, + bool &arch_different, + bool &vendor_different, + bool &os_different, + bool &os_version_different, + bool &env_different); + uint32_t GetFlags () const { diff --git a/include/lldb/Core/Broadcaster.h b/include/lldb/Core/Broadcaster.h index 6d54b1b43133..8e59a41805ec 100644 --- a/include/lldb/Core/Broadcaster.h +++ b/include/lldb/Core/Broadcaster.h @@ -42,7 +42,7 @@ public: BroadcastEventSpec (const BroadcastEventSpec &rhs); - ~BroadcastEventSpec() {} + ~BroadcastEventSpec() = default; const ConstString &GetBroadcasterClass() const { @@ -89,7 +89,7 @@ public: BroadcasterManager (); - ~BroadcasterManager () {} + ~BroadcasterManager() = default; uint32_t RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec); @@ -128,7 +128,7 @@ private: { } - ~BroadcasterClassMatches () {} + ~BroadcasterClassMatches() = default; bool operator() (const event_listener_key input) const { @@ -147,7 +147,7 @@ private: { } - ~BroadcastEventSpecMatches () {} + ~BroadcastEventSpecMatches() = default; bool operator() (const event_listener_key input) const { @@ -168,7 +168,7 @@ private: { } - ~ListenerMatchesAndSharedBits () {} + ~ListenerMatchesAndSharedBits() = default; bool operator() (const event_listener_key input) const { @@ -190,7 +190,7 @@ private: { } - ~ListenerMatches() {} + ~ListenerMatches() = default; bool operator () (const event_listener_key input) const { @@ -204,7 +204,6 @@ private: const Listener *m_listener; }; - }; //---------------------------------------------------------------------- @@ -286,10 +285,10 @@ public: BroadcastEventIfUnique (lldb::EventSP &event_sp); void - BroadcastEvent (uint32_t event_type, EventData *event_data = NULL); + BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr); void - BroadcastEventIfUnique (uint32_t event_type, EventData *event_data = NULL); + BroadcastEventIfUnique(uint32_t event_type, EventData *event_data = nullptr); void Clear(); @@ -332,7 +331,6 @@ public: const ConstString & GetBroadcasterName (); - //------------------------------------------------------------------ /// Get the event name(s) for one or more event bits. /// @@ -364,10 +362,10 @@ public: const char * GetEventName (uint32_t event_mask) const { - event_names_map::const_iterator pos = m_event_names.find (event_mask); + const auto pos = m_event_names.find (event_mask); if (pos != m_event_names.end()) return pos->second.c_str(); - return NULL; + return nullptr; } bool @@ -437,8 +435,6 @@ public: BroadcasterManager *GetManager(); protected: - - void PrivateBroadcastEvent (lldb::EventSP &event_sp, bool unique); diff --git a/include/lldb/Core/ClangForward.h b/include/lldb/Core/ClangForward.h index 6c627c2ad3b7..80abc15f671c 100644 --- a/include/lldb/Core/ClangForward.h +++ b/include/lldb/Core/ClangForward.h @@ -132,6 +132,8 @@ namespace clang namespace llvm { + class APInt; + class APSInt; class LLVMContext; class ExecutionEngine; } diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h index 7924ed293d3c..d29aaca9c2ea 100644 --- a/include/lldb/Core/Communication.h +++ b/include/lldb/Core/Communication.h @@ -100,7 +100,6 @@ public: typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len); - //------------------------------------------------------------------ /// Construct the Communication object with the specified name for /// the Broadcaster that this object inherits from. @@ -118,8 +117,7 @@ public: /// /// The destructor is virtual since this class gets subclassed. //------------------------------------------------------------------ - virtual - ~Communication(); + ~Communication() override; void Clear (); @@ -157,7 +155,7 @@ public: /// @see bool Connection::Disconnect (); //------------------------------------------------------------------ lldb::ConnectionStatus - Disconnect (Error *error_ptr = NULL); + Disconnect(Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Check if the connection is valid. @@ -177,6 +175,7 @@ public: { return m_connection_sp.get(); } + //------------------------------------------------------------------ /// Read bytes from the current connection. /// @@ -278,7 +277,7 @@ public: /// @see void Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast); //------------------------------------------------------------------ virtual bool - StartReadThread (Error *error_ptr = NULL); + StartReadThread(Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Stops the read thread by cancelling it. @@ -288,10 +287,10 @@ public: /// false otherwise. //------------------------------------------------------------------ virtual bool - StopReadThread (Error *error_ptr = NULL); + StopReadThread(Error *error_ptr = nullptr); virtual bool - JoinReadThread (Error *error_ptr = NULL); + JoinReadThread(Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Checks if there is a currently running read thread. /// @@ -323,7 +322,6 @@ public: SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback, void *callback_baton); - //------------------------------------------------------------------ /// Wait for the read thread to process all outstanding data. /// @@ -350,18 +348,11 @@ public: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } -private: - //------------------------------------------------------------------ - // For Communication only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (Communication); - - protected: lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use by this communications class. HostThread m_read_thread; ///< The read thread handle in case we need to cancel the thread. @@ -381,6 +372,7 @@ protected: uint32_t timeout_usec, lldb::ConnectionStatus &status, Error *error_ptr); + //------------------------------------------------------------------ /// Append new bytes that get read from the read thread into the /// internal object byte cache. This will cause a \b @@ -424,8 +416,11 @@ protected: //------------------------------------------------------------------ size_t GetCachedBytes (void *dst, size_t dst_len); + +private: + DISALLOW_COPY_AND_ASSIGN (Communication); }; } // namespace lldb_private -#endif // liblldb_Communication_h_ +#endif // liblldb_Communication_h_ diff --git a/include/lldb/Core/Connection.h b/include/lldb/Core/Connection.h index 121395c0b23c..4b3024ebdc57 100644 --- a/include/lldb/Core/Connection.h +++ b/include/lldb/Core/Connection.h @@ -58,7 +58,7 @@ public: /// /// @param[out] error_ptr /// A pointer to an error object that should be given an - /// approriate error value if this method returns false. This + /// appropriate error value if this method returns false. This /// value can be NULL if the error value should be ignored. /// /// @return @@ -77,7 +77,7 @@ public: /// /// @param[out] error_ptr /// A pointer to an error object that should be given an - /// approriate error value if this method returns false. This + /// appropriate error value if this method returns false. This /// value can be NULL if the error value should be ignored. /// /// @return @@ -115,12 +115,12 @@ public: /// The number of microseconds to wait for the data. /// /// @param[out] status - /// On return, indicates whether the call was sucessful or terminated + /// On return, indicates whether the call was successful or terminated /// due to some error condition. /// /// @param[out] error_ptr /// A pointer to an error object that should be given an - /// approriate error value if this method returns zero. This + /// appropriate error value if this method returns zero. This /// value can be NULL if the error value should be ignored. /// /// @return @@ -151,7 +151,7 @@ public: /// /// @param[out] error_ptr /// A pointer to an error object that should be given an - /// approriate error value if this method returns zero. This + /// appropriate error value if this method returns zero. This /// value can be NULL if the error value should be ignored. /// /// @return @@ -182,7 +182,7 @@ public: /// operation). /// /// @return - /// Returns true is the interrupt request was sucessful. + /// Returns true is the interrupt request was successful. //------------------------------------------------------------------ virtual bool InterruptRead() = 0; diff --git a/include/lldb/Core/ConnectionSharedMemory.h b/include/lldb/Core/ConnectionSharedMemory.h index 48e62142954e..d0553699e14e 100644 --- a/include/lldb/Core/ConnectionSharedMemory.h +++ b/include/lldb/Core/ConnectionSharedMemory.h @@ -28,33 +28,32 @@ public: ConnectionSharedMemory (); - virtual - ~ConnectionSharedMemory (); + ~ConnectionSharedMemory () override; - virtual bool - IsConnected () const; + bool + IsConnected () const override; virtual lldb::ConnectionStatus BytesAvailable (uint32_t timeout_usec, Error *error_ptr); - virtual lldb::ConnectionStatus - Connect (const char *s, Error *error_ptr); + lldb::ConnectionStatus + Connect (const char *s, Error *error_ptr) override; - virtual lldb::ConnectionStatus - Disconnect (Error *error_ptr); + lldb::ConnectionStatus + Disconnect (Error *error_ptr) override; - virtual size_t + size_t Read (void *dst, size_t dst_len, uint32_t timeout_usec, lldb::ConnectionStatus &status, - Error *error_ptr); + Error *error_ptr) override; - virtual size_t - Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + size_t + Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr) override; - virtual std::string - GetURI(); + std::string + GetURI() override; lldb::ConnectionStatus Open (bool create, const char *name, size_t size, Error *error_ptr); @@ -64,10 +63,12 @@ protected: std::string m_name; int m_fd; // One buffer that contains all we need DataBufferMemoryMap m_mmap; + private: + DISALLOW_COPY_AND_ASSIGN (ConnectionSharedMemory); }; } // namespace lldb_private -#endif // liblldb_ConnectionSharedMemory_h_ +#endif // liblldb_ConnectionSharedMemory_h_ diff --git a/include/lldb/Core/ConstString.h b/include/lldb/Core/ConstString.h index cfe8ea2db0e1..6e234da0a595 100644 --- a/include/lldb/Core/ConstString.h +++ b/include/lldb/Core/ConstString.h @@ -9,13 +9,14 @@ #ifndef liblldb_ConstString_h_ #define liblldb_ConstString_h_ -#if defined(__cplusplus) -#include - -#include "lldb/lldb-private.h" +// C Includes +// C++ Includes +// Other libraries and framework includes #include "llvm/ADT/StringRef.h" +// Project includes +#include "lldb/lldb-private.h" namespace lldb_private { @@ -41,12 +42,11 @@ public: /// /// Initializes the string to an empty string. //------------------------------------------------------------------ - ConstString (): - m_string (NULL) + ConstString(): + m_string(nullptr) { } - //------------------------------------------------------------------ /// Copy constructor /// @@ -105,10 +105,7 @@ public: /// Since constant string values are currently not reference counted, /// there isn't much to do here. //------------------------------------------------------------------ - ~ConstString () - { - } - + ~ConstString() = default; //---------------------------------------------------------------------- /// C string equality binary predicate function object for ConstString @@ -224,18 +221,16 @@ public: /// Get the value of the contained string as a NULL terminated C /// string value. /// - /// If \a value_if_empty is NULL, then NULL will be returned. + /// If \a value_if_empty is nullptr, then nullptr will be returned. /// /// @return /// Returns \a value_if_empty if the string is empty, otherwise /// the C string value contained in this object. //------------------------------------------------------------------ const char * - AsCString(const char *value_if_empty = NULL) const + AsCString(const char *value_if_empty = nullptr) const { - if (IsEmpty()) - return value_if_empty; - return m_string; + return (IsEmpty() ? value_if_empty : m_string); } //------------------------------------------------------------------ @@ -256,12 +251,12 @@ public: /// /// Get the value of the contained string as a NULL terminated C /// string value. Similar to the ConstString::AsCString() function, - /// yet this function will always return NULL if the string is not + /// yet this function will always return nullptr if the string is not /// valid. So this function is a direct accessor to the string /// pointer value. /// /// @return - /// Returns NULL the string is invalid, otherwise the C string + /// Returns nullptr the string is invalid, otherwise the C string /// value contained in this object. //------------------------------------------------------------------ const char * @@ -270,7 +265,6 @@ public: return m_string; } - //------------------------------------------------------------------ /// Get the length in bytes of string value. /// @@ -293,7 +287,7 @@ public: void Clear () { - m_string = NULL; + m_string = nullptr; } //------------------------------------------------------------------ @@ -326,18 +320,18 @@ public: /// /// Dump the string value to the stream \a s. If the contained string /// is empty, print \a value_if_empty to the stream instead. If - /// \a value_if_empty is NULL, then nothing will be dumped to the + /// \a value_if_empty is nullptr, then nothing will be dumped to the /// stream. /// /// @param[in] s /// The stream that will be used to dump the object description. /// /// @param[in] value_if_empty - /// The value to dump if the string is empty. If NULL, nothing + /// The value to dump if the string is empty. If nullptr, nothing /// will be output to the stream. //------------------------------------------------------------------ void - Dump (Stream *s, const char *value_if_empty = NULL) const; + Dump(Stream *s, const char *value_if_empty = nullptr) const; //------------------------------------------------------------------ /// Dump the object debug description to a stream. @@ -358,7 +352,7 @@ public: bool IsEmpty () const { - return m_string == NULL || m_string[0] == '\0'; + return m_string == nullptr || m_string[0] == '\0'; } //------------------------------------------------------------------ @@ -473,7 +467,6 @@ public: { return sizeof(ConstString); } - //------------------------------------------------------------------ /// Get the size in bytes of the current global string pool. @@ -503,5 +496,4 @@ Stream& operator << (Stream& s, const ConstString& str); } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_ConstString_h_ +#endif // liblldb_ConstString_h_ diff --git a/include/lldb/Core/DataBufferHeap.h b/include/lldb/Core/DataBufferHeap.h index ad73fabe5f1e..d379c4cf4e86 100644 --- a/include/lldb/Core/DataBufferHeap.h +++ b/include/lldb/Core/DataBufferHeap.h @@ -9,7 +9,6 @@ #ifndef liblldb_DataBufferHeap_h_ #define liblldb_DataBufferHeap_h_ -#if defined(__cplusplus) #include @@ -69,26 +68,25 @@ public: /// Virtual destructor since this class inherits from a pure virtual /// base class #DataBuffer. //------------------------------------------------------------------ - virtual - ~DataBufferHeap(); + ~DataBufferHeap() override; //------------------------------------------------------------------ /// @copydoc DataBuffer::GetBytes() //------------------------------------------------------------------ - virtual uint8_t * - GetBytes (); + uint8_t * + GetBytes () override; //------------------------------------------------------------------ /// @copydoc DataBuffer::GetBytes() const //------------------------------------------------------------------ - virtual const uint8_t * - GetBytes () const; + const uint8_t * + GetBytes () const override; //------------------------------------------------------------------ /// @copydoc DataBuffer::GetByteSize() const //------------------------------------------------------------------ - virtual lldb::offset_t - GetByteSize () const; + lldb::offset_t + GetByteSize () const override; //------------------------------------------------------------------ /// Set the number of bytes in the data buffer. @@ -138,5 +136,4 @@ private: } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_DataBufferHeap_h_ +#endif // liblldb_DataBufferHeap_h_ diff --git a/include/lldb/Core/DataBufferMemoryMap.h b/include/lldb/Core/DataBufferMemoryMap.h index 944b975a318a..9479d4e1a455 100644 --- a/include/lldb/Core/DataBufferMemoryMap.h +++ b/include/lldb/Core/DataBufferMemoryMap.h @@ -9,8 +9,6 @@ #ifndef liblldb_DataBufferMemoryMap_h_ #define liblldb_DataBufferMemoryMap_h_ -#if defined(__cplusplus) - #include "lldb/lldb-private.h" #include "lldb/Core/DataBuffer.h" @@ -45,8 +43,7 @@ public: /// Virtual destructor since this class inherits from a pure virtual /// base class #DataBuffer. //------------------------------------------------------------------ - virtual - ~DataBufferMemoryMap (); + ~DataBufferMemoryMap () override; //------------------------------------------------------------------ /// Reverts this object to an empty state by unmapping any memory @@ -58,20 +55,20 @@ public: //------------------------------------------------------------------ /// @copydoc DataBuffer::GetBytes() //------------------------------------------------------------------ - virtual uint8_t * - GetBytes (); + uint8_t * + GetBytes () override; //------------------------------------------------------------------ /// @copydoc DataBuffer::GetBytes() const //------------------------------------------------------------------ - virtual const uint8_t * - GetBytes () const; + const uint8_t * + GetBytes () const override; //------------------------------------------------------------------ /// @copydoc DataBuffer::GetByteSize() const //------------------------------------------------------------------ - virtual lldb::offset_t - GetByteSize () const; + lldb::offset_t + GetByteSize () const override; //------------------------------------------------------------------ /// Error get accessor. @@ -161,5 +158,4 @@ private: } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_DataBufferMemoryMap_h_ +#endif // liblldb_DataBufferMemoryMap_h_ diff --git a/include/lldb/Core/DataEncoder.h b/include/lldb/Core/DataEncoder.h index 7889f4191e50..8b4727eb2de2 100644 --- a/include/lldb/Core/DataEncoder.h +++ b/include/lldb/Core/DataEncoder.h @@ -252,7 +252,7 @@ public: /// The offset in bytes into the contained data at which to /// start encoding. /// - /// @param[int] src + /// @param[in] src /// The buffer that contains the bytes to encode. /// /// @param[in] src_len diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h index e61189b98103..d5cb5e8ba4bc 100644 --- a/include/lldb/Core/DataExtractor.h +++ b/include/lldb/Core/DataExtractor.h @@ -9,17 +9,18 @@ #ifndef liblldb_DataExtractor_h_ #define liblldb_DataExtractor_h_ -#if defined (__cplusplus) - - -#include "lldb/lldb-private.h" - -#include "llvm/ADT/SmallVector.h" +// C Includes #include #include #include -#include + +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/SmallVector.h" + +// Project includes +#include "lldb/lldb-private.h" namespace lldb_private { @@ -64,6 +65,7 @@ public: size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr); // Pass LLDB_INVALID_ADDRESS to not show address at start of line + //------------------------------------------------------------------ /// Default constructor. /// @@ -146,6 +148,7 @@ public: DataExtractor (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length, uint32_t target_byte_size = 1); DataExtractor (const DataExtractor& rhs); + //------------------------------------------------------------------ /// Assignment operator. /// @@ -183,14 +186,14 @@ public: //------------------------------------------------------------------ /// Dumps the binary data as \a type objects to stream \a s (or to - /// Log() if \a s is NULL) starting \a offset bytes into the data + /// Log() if \a s is nullptr) starting \a offset bytes into the data /// and stopping after dumping \a length bytes. The offset into the /// data is displayed at the beginning of each line and can be /// offset by base address \a base_addr. \a num_per_line objects /// will be displayed on each line. /// /// @param[in] s - /// The stream to dump the output to. If NULL the output will + /// The stream to dump the output to. If nullptr the output will /// be dumped to Log(). /// /// @param[in] offset @@ -212,19 +215,19 @@ public: /// /// @param[in] type_format /// The optional format to use for the \a type objects. If this - /// is NULL, the default format for the \a type will be used. + /// is nullptr, the default format for the \a type will be used. /// /// @return /// The offset at which dumping ended. //------------------------------------------------------------------ lldb::offset_t - PutToLog (Log *log, - lldb::offset_t offset, - lldb::offset_t length, - uint64_t base_addr, - uint32_t num_per_line, - Type type, - const char *type_format = NULL) const; + PutToLog(Log *log, + lldb::offset_t offset, + lldb::offset_t length, + uint64_t base_addr, + uint32_t num_per_line, + Type type, + const char *type_format = nullptr) const; //------------------------------------------------------------------ /// Dumps \a item_count objects into the stream \a s. @@ -241,7 +244,7 @@ public: /// item_bit_size and \a item_bit_offset values. /// /// @param[in] s - /// The stream to dump the output to. This value can not be NULL. + /// The stream to dump the output to. This value can not be nullptr. /// /// @param[in] offset /// The offset into the data at which to start dumping. @@ -287,25 +290,25 @@ public: /// The offset at which dumping ended. //------------------------------------------------------------------ lldb::offset_t - Dump (Stream *s, - lldb::offset_t offset, - lldb::Format item_format, - size_t item_byte_size, - size_t item_count, - size_t num_per_line, - uint64_t base_addr, - uint32_t item_bit_size, - uint32_t item_bit_offset, - ExecutionContextScope *exe_scope = NULL) const; + Dump(Stream *s, + lldb::offset_t offset, + lldb::Format item_format, + size_t item_byte_size, + size_t item_count, + size_t num_per_line, + uint64_t base_addr, + uint32_t item_bit_size, + uint32_t item_bit_offset, + ExecutionContextScope *exe_scope = nullptr) const; //------------------------------------------------------------------ /// Dump a UUID value at \a offset. /// /// Dump a UUID starting at \a offset bytes into this object's data. - /// If the stream \a s is NULL, the output will be sent to Log(). + /// If the stream \a s is nullptr, the output will be sent to Log(). /// /// @param[in] s - /// The stream to dump the output to. If NULL the output will + /// The stream to dump the output to. If nullptr the output will /// be dumped to Log(). /// /// @param[in] offset @@ -418,7 +421,7 @@ public: /// A pointer to the C string value in the data. If the offset /// pointed to by \a offset_ptr is out of bounds, or if the /// offset plus the length of the C string is out of bounds, - /// NULL will be returned. + /// nullptr will be returned. //------------------------------------------------------------------ const char * GetCStr (lldb::offset_t *offset_ptr) const; @@ -443,7 +446,7 @@ public: /// A pointer to the C string value in the data. If the offset /// pointed to by \a offset_ptr is out of bounds, or if the /// offset plus the length of the field is out of bounds, or if - /// the field does not contain a NULL terminator byte, NULL will + /// the field does not contain a NULL terminator byte, nullptr will /// be returned. const char * GetCStr (lldb::offset_t *offset_ptr, lldb::offset_t len) const; @@ -454,7 +457,7 @@ public: /// Returns a pointer to a bytes in this object's data at the offset /// pointed to by \a offset_ptr. If \a length is zero or too large, /// then the offset pointed to by \a offset_ptr will not be updated - /// and NULL will be returned. + /// and nullptr will be returned. /// /// @param[in,out] offset_ptr /// A pointer to an offset within the data that will be advanced @@ -469,7 +472,7 @@ public: /// /// @return /// A pointer to the bytes in this object's data if the offset - /// and length are valid, or NULL otherwise. + /// and length are valid, or nullptr otherwise. //------------------------------------------------------------------ const void* GetData (lldb::offset_t *offset_ptr, lldb::offset_t length) const @@ -552,7 +555,7 @@ public: /// /// @return /// Returns a pointer to the next byte contained in this - /// object's data, or NULL of there is no data in this object. + /// object's data, or nullptr of there is no data in this object. //------------------------------------------------------------------ const uint8_t * GetDataEnd () const @@ -578,7 +581,7 @@ public: /// /// @return /// Returns a pointer to the first byte contained in this - /// object's data, or NULL of there is no data in this object. + /// object's data, or nullptr of there is no data in this object. //------------------------------------------------------------------ const uint8_t * GetDataStart () const @@ -586,7 +589,6 @@ public: return m_start; } - //------------------------------------------------------------------ /// Extract a float from \a *offset_ptr. /// @@ -908,7 +910,7 @@ public: /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherwise. + /// nullptr otherwise. //------------------------------------------------------------------ void * GetU8 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -955,7 +957,7 @@ public: /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherwise. + /// nullptr otherwise. //------------------------------------------------------------------ void * GetU16 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1002,7 +1004,7 @@ public: /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherwise. + /// nullptr otherwise. //------------------------------------------------------------------ void * GetU32 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1049,7 +1051,7 @@ public: /// /// @return /// \a dst if all values were properly extracted and copied, - /// NULL otherwise. + /// nullptr otherwise. //------------------------------------------------------------------ void * GetU64 ( lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; @@ -1113,8 +1115,8 @@ public: /// An offset into the data. /// /// @return - /// A non-NULL C string pointer if \a offset is a valid offset, - /// NULL otherwise. + /// A non-nullptr C string pointer if \a offset is a valid offset, + /// nullptr otherwise. //------------------------------------------------------------------ const char * PeekCStr (lldb::offset_t offset) const; @@ -1126,8 +1128,8 @@ public: /// there are \a length bytes available starting at \a offset. /// /// @return - /// A non-NULL data pointer if \a offset is a valid offset and - /// there are \a length bytes available at that offset, NULL + /// A non-nullptr data pointer if \a offset is a valid offset and + /// there are \a length bytes available at that offset, nullptr /// otherwise. //------------------------------------------------------------------ const uint8_t* @@ -1135,7 +1137,7 @@ public: { if (length > 0 && ValidOffsetForDataOfSize(offset, length)) return m_start + offset; - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -1150,6 +1152,9 @@ public: void SetAddressByteSize (uint32_t addr_size) { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (addr_size == 4 || addr_size == 8); +#endif m_addr_size = addr_size; } @@ -1159,7 +1164,7 @@ public: /// Use data that is owned by the caller when extracting values. /// The data must stay around as long as this object, or any object /// that copies a subset of this object's data, is valid. If \a - /// bytes is NULL, or \a length is zero, this object will contain + /// bytes is nullptr, or \a length is zero, this object will contain /// no data. /// /// @param[in] bytes @@ -1317,10 +1322,8 @@ public: void Checksum (llvm::SmallVectorImpl &dest, uint64_t max_data = 0); - protected: - //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ @@ -1334,5 +1337,4 @@ protected: } // namespace lldb_private -#endif // #if defined (__cplusplus) -#endif // #ifndef liblldb_DataExtractor_h_ +#endif // liblldb_DataExtractor_h_ diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h index 0d9b90c8919d..4ca648ca296e 100644 --- a/include/lldb/Core/Debugger.h +++ b/include/lldb/Core/Debugger.h @@ -9,11 +9,17 @@ #ifndef liblldb_Debugger_h_ #define liblldb_Debugger_h_ -#if defined(__cplusplus) - +// C Includes #include +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/FormatEntity.h" @@ -32,8 +38,8 @@ namespace llvm namespace sys { class DynamicLibrary; -} -} +} // namespace sys +} // namespace llvm namespace lldb_private { @@ -44,7 +50,6 @@ namespace lldb_private { /// Provides a global root objects for the debugger core. //---------------------------------------------------------------------- - class Debugger : public std::enable_shared_from_this, public UserID, @@ -54,9 +59,10 @@ class Debugger : friend class SourceManager; // For GetSourceFileCache. public: + ~Debugger() override; static lldb::DebuggerSP - CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL); + CreateInstance(lldb::LogOutputCallback log_callback = nullptr, void *baton = nullptr); static lldb::TargetSP FindTargetWithProcessID (lldb::pid_t pid); @@ -79,9 +85,26 @@ public: static void Destroy (lldb::DebuggerSP &debugger_sp); - virtual - ~Debugger (); + static lldb::DebuggerSP + FindDebuggerWithID(lldb::user_id_t id); + static lldb::DebuggerSP + FindDebuggerWithInstanceName(const ConstString &instance_name); + + static size_t + GetNumDebuggers(); + + static lldb::DebuggerSP + GetDebuggerAtIndex(size_t index); + + static bool + FormatDisassemblerAddress(const FormatEntity::Entry *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, + Stream &s); + void Clear(); bool @@ -108,8 +131,6 @@ public: return m_error_file_sp; } - - void SetInputFileHandle (FILE *fh, bool tranfer_ownership); @@ -209,6 +230,10 @@ public: bool IsTopIOHandler (const lldb::IOHandlerSP& reader_sp); + + bool + CheckTopIOHandlerTypes (IOHandler::Type top_type, + IOHandler::Type second_top_type); void PrintAsync (const char *s, size_t len, bool is_stdout); @@ -222,26 +247,6 @@ public: const char * GetIOHandlerHelpPrologue(); - static lldb::DebuggerSP - FindDebuggerWithID (lldb::user_id_t id); - - static lldb::DebuggerSP - FindDebuggerWithInstanceName (const ConstString &instance_name); - - static size_t - GetNumDebuggers(); - - static lldb::DebuggerSP - GetDebuggerAtIndex (size_t index); - - static bool - FormatDisassemblerAddress (const FormatEntity::Entry *format, - const SymbolContext *sc, - const SymbolContext *prev_sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s); - void ClearIOHandlers (); @@ -257,22 +262,22 @@ public: void SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton); - //---------------------------------------------------------------------- // Properties Functions //---------------------------------------------------------------------- enum StopDisassemblyType { eStopDisassemblyTypeNever = 0, + eStopDisassemblyTypeNoDebugInfo, eStopDisassemblyTypeNoSource, eStopDisassemblyTypeAlways }; - virtual Error - SetPropertyValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *property_path, - const char *value); + Error + SetPropertyValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *property_path, + const char *value) override; bool GetAutoConfirm () const; @@ -328,6 +333,24 @@ public: bool GetAutoOneLineSummaries () const; + bool + GetAutoIndent () const; + + bool + SetAutoIndent (bool b); + + bool + GetPrintDecls () const; + + bool + SetPrintDecls (bool b); + + uint32_t + GetTabSize () const; + + bool + SetTabSize (uint32_t tab_size); + bool GetEscapeNonPrintables () const; @@ -360,6 +383,9 @@ public: { return m_event_handler_thread.IsJoinable(); } + + Error + RunREPL (lldb::LanguageType language, const char *repl_options); // This is for use in the command interpreter, when you either want the selected target, or if no target // is present you want to prime the dummy target with entities that will be copied over to new targets. @@ -367,8 +393,8 @@ public: Target *GetDummyTarget(); protected: - friend class CommandInterpreter; + friend class REPL; bool StartEventHandlerThread(); @@ -379,12 +405,18 @@ protected: static lldb::thread_result_t EventHandlerThread (lldb::thread_arg_t arg); + bool + HasIOHandlerThread(); + bool StartIOHandlerThread(); void StopIOHandlerThread(); + void + JoinIOHandlerThread(); + static lldb::thread_result_t IOHandlerThread (lldb::thread_arg_t arg); @@ -450,16 +482,13 @@ protected: }; private: - // Use Debugger::CreateInstance() to get a shared pointer to a new // debugger object Debugger (lldb::LogOutputCallback m_log_callback, void *baton); DISALLOW_COPY_AND_ASSIGN (Debugger); - }; } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_Debugger_h_ +#endif // liblldb_Debugger_h_ diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index e08e2def4c18..bfa99de81ea4 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -48,6 +48,7 @@ public: CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); return m_opcode_name.c_str(); } + const char * GetOperands (const ExecutionContext* exe_ctx) { @@ -127,7 +128,6 @@ public: /// so this method can properly align the instruction opcodes. /// May be 0 to indicate no indentation/alignment of the opcodes. //------------------------------------------------------------------ - virtual void Dump (Stream *s, uint32_t max_opcode_byte_size, @@ -142,6 +142,9 @@ public: virtual bool DoesBranch () = 0; + virtual bool + HasDelaySlot (); + virtual size_t Decode (const Disassembler &disassembler, const DataExtractor& data, @@ -208,7 +211,6 @@ protected: } }; - class InstructionList { public: @@ -260,30 +262,32 @@ public: PseudoInstruction (); - virtual - ~PseudoInstruction (); + ~PseudoInstruction() override; - virtual bool - DoesBranch (); + bool + DoesBranch() override; - virtual void - CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx) + bool + HasDelaySlot() override; + + void + CalculateMnemonicOperandsAndComment(const ExecutionContext* exe_ctx) override { // TODO: fill this in and put opcode name into Instruction::m_opcode_name, // mnemonic into Instruction::m_mnemonics, and any comment into // Instruction::m_comment } - virtual size_t - Decode (const Disassembler &disassembler, - const DataExtractor &data, - lldb::offset_t data_offset); + size_t + Decode(const Disassembler &disassembler, + const DataExtractor &data, + lldb::offset_t data_offset) override; void SetOpcode (size_t opcode_size, void *opcode_data); - virtual void - SetDescription (const char *description); + void + SetDescription(const char *description) override; protected: std::string m_description; @@ -405,7 +409,7 @@ public: // Constructors and Destructors //------------------------------------------------------------------ Disassembler(const ArchSpec &arch, const char *flavor); - virtual ~Disassembler(); + ~Disassembler() override; typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data); @@ -478,4 +482,4 @@ private: } // namespace lldb_private -#endif // liblldb_Disassembler_h_ +#endif // liblldb_Disassembler_h_ diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h index 774d80968ff9..c5e60022fc96 100644 --- a/include/lldb/Core/EmulateInstruction.h +++ b/include/lldb/Core/EmulateInstruction.h @@ -19,6 +19,8 @@ #include "lldb/Core/Opcode.h" #include "lldb/Core/RegisterValue.h" +namespace lldb_private { + //---------------------------------------------------------------------- /// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h" /// @brief A class that allows emulation of CPU opcodes. @@ -79,8 +81,6 @@ /// and emulating the instruction is just a bonus. //---------------------------------------------------------------------- -namespace lldb_private { - class EmulateInstruction : public PluginInterface { @@ -233,7 +233,6 @@ public: } ISAAndImmediateSigned; uint32_t isa; - } info; Context () : @@ -387,9 +386,8 @@ public: EmulateInstruction (const ArchSpec &arch); - virtual ~EmulateInstruction() - { - } + ~EmulateInstruction() override = default; + //---------------------------------------------------------------------- // Mandatory overrides //---------------------------------------------------------------------- @@ -404,7 +402,10 @@ public: virtual bool EvaluateInstruction (uint32_t evaluate_options) = 0; - + + virtual bool + IsInstructionConditional() { return false; } + virtual bool TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; @@ -527,7 +528,6 @@ public: return m_arch; } - static size_t ReadMemoryFrame (EmulateInstruction *instruction, void *baton, @@ -628,7 +628,6 @@ protected: lldb::addr_t m_addr; Opcode m_opcode; - private: //------------------------------------------------------------------ // For EmulateInstruction only @@ -636,6 +635,6 @@ private: DISALLOW_COPY_AND_ASSIGN (EmulateInstruction); }; -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_EmulateInstruction_h_ +#endif // lldb_EmulateInstruction_h_ diff --git a/include/lldb/Core/Event.h b/include/lldb/Core/Event.h index 1c3eec0359c3..e8867c0e7e77 100644 --- a/include/lldb/Core/Event.h +++ b/include/lldb/Core/Event.h @@ -12,7 +12,7 @@ // C Includes // C++ Includes -#include +#include #include // Other libraries and framework includes @@ -49,7 +49,6 @@ private: } DISALLOW_COPY_AND_ASSIGN (EventData); - }; //---------------------------------------------------------------------- @@ -67,17 +66,16 @@ public: EventDataBytes (const void *src, size_t src_len); - virtual - ~EventDataBytes(); + ~EventDataBytes() override; //------------------------------------------------------------------ // Member functions //------------------------------------------------------------------ - virtual const ConstString & - GetFlavor () const; + const ConstString & + GetFlavor () const override; - virtual void - Dump (Stream *s) const; + void + Dump (Stream *s) const override; const void * GetBytes() const; @@ -113,7 +111,6 @@ private: std::string m_bytes; DISALLOW_COPY_AND_ASSIGN (EventDataBytes); - }; //---------------------------------------------------------------------- @@ -126,10 +123,9 @@ class Event friend class EventData; public: + Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data = nullptr); - Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data = NULL); - - Event (uint32_t event_type, EventData *data = NULL); + Event(uint32_t event_type, EventData *data = nullptr); ~Event (); @@ -184,7 +180,6 @@ public: m_data_ap.reset(); } - private: // This is only called by Listener when it pops an event off the queue for // the listener. It calls the Event Data's DoOnRemoval() method, which is @@ -202,7 +197,6 @@ private: m_broadcaster = broadcaster; } - Broadcaster * m_broadcaster; // The broadcaster that sent this event uint32_t m_type; // The bit describing this event std::unique_ptr m_data_ap; // User specific data for this event @@ -214,4 +208,4 @@ private: } // namespace lldb_private -#endif // liblldb_Event_h_ +#endif // liblldb_Event_h_ diff --git a/include/lldb/Core/FileLineResolver.h b/include/lldb/Core/FileLineResolver.h index e1928f1b063d..f0f7fbdf756f 100644 --- a/include/lldb/Core/FileLineResolver.h +++ b/include/lldb/Core/FileLineResolver.h @@ -38,20 +38,19 @@ public: uint32_t line_no, bool check_inlines); - virtual - ~FileLineResolver (); + ~FileLineResolver () override; - virtual Searcher::CallbackReturn + Searcher::CallbackReturn SearchCallback (SearchFilter &filter, SymbolContext &context, Address *addr, - bool containing); + bool containing) override; - virtual Searcher::Depth - GetDepth (); + Searcher::Depth + GetDepth () override; - virtual void - GetDescription (Stream *s); + void + GetDescription (Stream *s) override; const SymbolContextList & GetFileLineMatches() @@ -78,4 +77,4 @@ private: } // namespace lldb_private -#endif // liblldb_FileLineResolver_h_ +#endif // liblldb_FileLineResolver_h_ diff --git a/include/lldb/Core/FormatEntity.h b/include/lldb/Core/FormatEntity.h index db4f59132832..659b696e61fd 100644 --- a/include/lldb/Core/FormatEntity.h +++ b/include/lldb/Core/FormatEntity.h @@ -9,18 +9,21 @@ #ifndef liblldb_FormatEntity_h_ #define liblldb_FormatEntity_h_ -#if defined(__cplusplus) +// C Includes +// C++ Includes #include #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Error.h" namespace llvm { class StringRef; -} +} // namespace llvm namespace lldb_private { @@ -81,6 +84,7 @@ namespace lldb_private FunctionPCOffset, FunctionInitial, FunctionChanged, + FunctionIsOptimized, LineEntryFile, LineEntryLineNumber, LineEntryStartAddress, @@ -108,13 +112,13 @@ namespace lldb_private bool keep_separator; }; - Entry (Type t = Type::Invalid, - const char *s = NULL, - const char *f = NULL) : + Entry(Type t = Type::Invalid, + const char *s = nullptr, + const char *f = nullptr) : string (s ? s : ""), printf_format (f ? f : ""), children (), - definition (NULL), + definition (nullptr), type (t), fmt (lldb::eFormatDefault), number (0), @@ -146,7 +150,7 @@ namespace lldb_private string.clear(); printf_format.clear(); children.clear(); - definition = NULL; + definition = nullptr; type = Type::Invalid; fmt = lldb::eFormatDefault; number = 0; @@ -252,12 +256,10 @@ namespace lldb_private static bool FormatFileSpec (const FileSpec &file, Stream &s, llvm::StringRef elements, llvm::StringRef element_format); protected: - static Error ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth); }; +} // namespace lldb_private -} -#endif // #if defined(__cplusplus) -#endif // liblldb_FormatEntity_h_ +#endif // liblldb_FormatEntity_h_ diff --git a/include/lldb/Core/History.h b/include/lldb/Core/History.h index b3626882f843..fbb7bd8b0c1a 100644 --- a/include/lldb/Core/History.h +++ b/include/lldb/Core/History.h @@ -82,7 +82,6 @@ private: collection m_events; DISALLOW_COPY_AND_ASSIGN (HistorySource); - }; //---------------------------------------------------------------------- @@ -103,8 +102,7 @@ class HistorySourceUInt : public HistorySource { } - virtual - ~HistorySourceUInt() + ~HistorySourceUInt() override { } @@ -112,44 +110,44 @@ class HistorySourceUInt : public HistorySource // in the subclass of this class to produce a history event and push it // onto the end of the history stack. - virtual HistoryEvent - CreateHistoryEvent () + HistoryEvent + CreateHistoryEvent () override { ++m_curr_id; return (HistoryEvent)m_curr_id; } - virtual void - DeleteHistoryEvent (HistoryEvent event) + void + DeleteHistoryEvent (HistoryEvent event) override { // Nothing to delete, the event contains the integer } - virtual void - DumpHistoryEvent (Stream &strm, HistoryEvent event); + void + DumpHistoryEvent (Stream &strm, HistoryEvent event) override; - virtual size_t - GetHistoryEventCount() + size_t + GetHistoryEventCount() override { return m_curr_id; } - virtual HistoryEvent - GetHistoryEventAtIndex (uint32_t idx) + HistoryEvent + GetHistoryEventAtIndex (uint32_t idx) override { return (HistoryEvent)((uintptr_t)idx); } - virtual HistoryEvent - GetCurrentHistoryEvent () + HistoryEvent + GetCurrentHistoryEvent () override { return (HistoryEvent)m_curr_id; } // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs. - virtual int + int CompareHistoryEvents (const HistoryEvent lhs, - const HistoryEvent rhs) + const HistoryEvent rhs) override { uintptr_t lhs_uint = (uintptr_t)lhs; uintptr_t rhs_uint = (uintptr_t)rhs; @@ -160,8 +158,8 @@ class HistorySourceUInt : public HistorySource return 0; } - virtual bool - IsCurrentHistoryEvent (const HistoryEvent event) + bool + IsCurrentHistoryEvent (const HistoryEvent event) override { return (uintptr_t)event == m_curr_id; } @@ -171,7 +169,6 @@ protected: uintptr_t m_curr_id; // The current value of the history unsigned unteger }; - } // namespace lldb_private -#endif // lldb_History_h_ +#endif // lldb_History_h_ diff --git a/include/lldb/Core/IOHandler.h b/include/lldb/Core/IOHandler.h index b617d8e75f58..3eba1c3cc9d8 100644 --- a/include/lldb/Core/IOHandler.h +++ b/include/lldb/Core/IOHandler.h @@ -10,10 +10,16 @@ #ifndef liblldb_IOHandler_h_ #define liblldb_IOHandler_h_ +// C Includes #include -#include +// C++ Includes +#include +#include +#include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/ConstString.h" @@ -29,7 +35,7 @@ namespace curses { class Application; typedef std::unique_ptr ApplicationAP; -} +} // namespace curses namespace lldb_private { @@ -42,6 +48,7 @@ namespace lldb_private { Confirm, Curses, Expression, + REPL, ProcessIO, PythonInterpreter, PythonCode, @@ -123,7 +130,7 @@ namespace lldb_private { GetPrompt () { // Prompt support isn't mandatory - return NULL; + return nullptr; } virtual bool @@ -142,13 +149,13 @@ namespace lldb_private { virtual const char * GetCommandPrefix () { - return NULL; + return nullptr; } virtual const char * GetHelpPrologue() { - return NULL; + return nullptr; } int @@ -257,7 +264,6 @@ namespace lldb_private { private: DISALLOW_COPY_AND_ASSIGN (IOHandler); }; - //------------------------------------------------------------------ /// A delegate class for use with IOHandler subclasses. @@ -283,9 +289,7 @@ namespace lldb_private { } virtual - ~IOHandlerDelegate() - { - } + ~IOHandlerDelegate() = default; virtual void IOHandlerActivated (IOHandler &io_handler) @@ -309,7 +313,7 @@ namespace lldb_private { virtual const char * IOHandlerGetFixIndentationCharacters () { - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -395,13 +399,13 @@ namespace lldb_private { virtual const char * IOHandlerGetCommandPrefix () { - return NULL; + return nullptr; } virtual const char * IOHandlerGetHelpPrologue () { - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -415,6 +419,7 @@ namespace lldb_private { { return false; } + protected: Completion m_completion; // Support for common builtin completions bool m_io_handler_done; @@ -438,10 +443,7 @@ namespace lldb_private { { } - virtual - ~IOHandlerDelegateMultiline () - { - } + ~IOHandlerDelegateMultiline() override = default; ConstString IOHandlerGetControlSequence (char ch) override @@ -467,11 +469,11 @@ namespace lldb_private { } return false; } + protected: const std::string m_end_line; }; - class IOHandlerEditline : public IOHandler { public: @@ -499,8 +501,7 @@ namespace lldb_private { uint32_t line_number_start, // If non-zero show line numbers starting at 'line_number_start' IOHandlerDelegate &delegate); - virtual - ~IOHandlerEditline (); + ~IOHandlerEditline() override; void Run () override; @@ -632,8 +633,7 @@ namespace lldb_private { const char *prompt, bool default_response); - virtual - ~IOHandlerConfirm (); + ~IOHandlerConfirm() override; bool GetResponse () const @@ -694,14 +694,14 @@ namespace lldb_private { public: IOHandlerCursesValueObjectList (Debugger &debugger, ValueObjectList &valobj_list); - virtual - ~IOHandlerCursesValueObjectList (); + ~IOHandlerCursesValueObjectList() override; void Run () override; void GotEOF() override; + protected: ValueObjectList m_valobj_list; }; @@ -709,17 +709,14 @@ namespace lldb_private { class IOHandlerStack { public: - IOHandlerStack () : m_stack(), m_mutex(Mutex::eMutexTypeRecursive), - m_top (NULL) + m_top (nullptr) { } - ~IOHandlerStack () - { - } + ~IOHandlerStack() = default; size_t GetSize () const @@ -771,10 +768,8 @@ namespace lldb_private { sp->SetPopped (true); } // Set m_top the non-locking IsTop() call - if (m_stack.empty()) - m_top = NULL; - else - m_top = m_stack.back().get(); + + m_top = (m_stack.empty() ? nullptr : m_stack.back().get()); } Mutex & @@ -794,53 +789,42 @@ namespace lldb_private { { Mutex::Locker locker (m_mutex); const size_t num_io_handlers = m_stack.size(); - if (num_io_handlers >= 2 && - m_stack[num_io_handlers-1]->GetType() == top_type && - m_stack[num_io_handlers-2]->GetType() == second_top_type) - { - return true; - } - return false; + return (num_io_handlers >= 2 && + m_stack[num_io_handlers-1]->GetType() == top_type && + m_stack[num_io_handlers-2]->GetType() == second_top_type); } + ConstString GetTopIOHandlerControlSequence (char ch) { - if (m_top) - return m_top->GetControlSequence(ch); - return ConstString(); + return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString()); } const char * GetTopIOHandlerCommandPrefix() { - if (m_top) - return m_top->GetCommandPrefix(); - return NULL; + return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr); } const char * GetTopIOHandlerHelpPrologue() { - if (m_top) - return m_top->GetHelpPrologue(); - return NULL; + return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr); } void PrintAsync (Stream *stream, const char *s, size_t len); protected: - typedef std::vector collection; collection m_stack; mutable Mutex m_mutex; IOHandler *m_top; private: - DISALLOW_COPY_AND_ASSIGN (IOHandlerStack); }; } // namespace lldb_private -#endif // #ifndef liblldb_IOHandler_h_ +#endif // liblldb_IOHandler_h_ diff --git a/include/lldb/Core/Language.h b/include/lldb/Core/Language.h deleted file mode 100644 index 670c6aa695e1..000000000000 --- a/include/lldb/Core/Language.h +++ /dev/null @@ -1,117 +0,0 @@ -//===-- Language.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_Language_h_ -#define liblldb_Language_h_ - -#include "lldb/lldb-private.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class Language Language.h "lldb/Core/Language.h" -/// @brief Encapsulates the programming language for an lldb object. -/// -/// Languages are represented by an enumeration value. -/// -/// The enumeration values used when describing the programming language -/// are the same values as the latest DWARF specification. -//---------------------------------------------------------------------- -class Language -{ -public: - //------------------------------------------------------------------ - /// Construct with optional language enumeration. - //------------------------------------------------------------------ - Language(lldb::LanguageType language = lldb::eLanguageTypeUnknown); - - //------------------------------------------------------------------ - /// Destructor. - /// - /// The destructor is virtual in case this class is subclassed. - //------------------------------------------------------------------ - virtual - ~Language(); - - //------------------------------------------------------------------ - /// Get the language value as a NULL termianted C string. - /// - /// @return - /// The C string representation of the language. The returned - /// string does not need to be freed as it comes from constant - /// strings. NULL can be returned when the language is set to - /// a value that doesn't match of of the lldb::LanguageType - /// enumerations. - //------------------------------------------------------------------ - const char * - AsCString (lldb::DescriptionLevel level = lldb::eDescriptionLevelBrief) const; - - void - Clear(); - - void - GetDescription (Stream *s, lldb::DescriptionLevel level) const; - - //------------------------------------------------------------------ - /// Dump the language value to the stream \a s. - /// - /// @param[in] s - /// The stream to which to dump the language description. - //------------------------------------------------------------------ - void - Dump(Stream *s) const; - - //------------------------------------------------------------------ - /// Get accessor for the language. - /// - /// @return - /// The enumeration value that describes the programming - /// language that an object is associated with. - //------------------------------------------------------------------ - virtual lldb::LanguageType - GetLanguage() const; - - //------------------------------------------------------------------ - /// Set accessor for the language. - /// - /// @param[in] language - /// The new enumeration value that describes the programming - /// language that an object is associated with. - //------------------------------------------------------------------ - void - SetLanguage(lldb::LanguageType language); - - //------------------------------------------------------------------ - /// Set accessor for the language. - /// - /// @param[in] language_cstr - /// The language name as a C string. - //------------------------------------------------------------------ - bool - SetLanguageFromCString(const char *language_cstr); - - -protected: - //------------------------------------------------------------------ - // Member variables - //------------------------------------------------------------------ - lldb::LanguageType m_language; ///< The programming language enumeration value. - ///< The enumeration values are the same as the - ///< latest DWARF specification. -}; - -//-------------------------------------------------------------- -/// Stream the language enumeration as a string object to a -/// Stream. -//-------------------------------------------------------------- -Stream& operator << (Stream& s, const Language& language); - -} // namespace lldb_private - -#endif // liblldb_Language_h_ diff --git a/include/lldb/Core/Listener.h b/include/lldb/Core/Listener.h index 2dbd2eb436ce..b11c1644507b 100644 --- a/include/lldb/Core/Listener.h +++ b/include/lldb/Core/Listener.h @@ -14,11 +14,9 @@ // C++ Includes #include #include -#include #include #include - // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -118,13 +116,12 @@ public: HandleBroadcastEvent (lldb::EventSP &event_sp); private: - //------------------------------------------------------------------ // Classes that inherit from Listener can see and modify these //------------------------------------------------------------------ struct BroadcasterInfo { - BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = NULL, void *ud = NULL) : + BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = nullptr, void *ud = nullptr) : event_mask (mask), callback (cb), callback_user_data (ud) @@ -141,28 +138,28 @@ private: typedef std::vector broadcaster_manager_collection; bool - FindNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster - const ConstString *sources, // NULL for any event - uint32_t num_sources, - uint32_t event_type_mask, - lldb::EventSP &event_sp, - bool remove); + FindNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *sources, // nullptr for any event + uint32_t num_sources, + uint32_t event_type_mask, + lldb::EventSP &event_sp, + bool remove); + + bool + GetNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *sources, // nullptr for any event + uint32_t num_sources, + uint32_t event_type_mask, + lldb::EventSP &event_sp); bool - GetNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster - const ConstString *sources, // NULL for any event + WaitForEventsInternal(const TimeValue *timeout, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *sources, // nullptr for any event uint32_t num_sources, uint32_t event_type_mask, lldb::EventSP &event_sp); - bool - WaitForEventsInternal (const TimeValue *timeout, - Broadcaster *broadcaster, // NULL for any broadcaster - const ConstString *sources, // NULL for any event - uint32_t num_sources, - uint32_t event_type_mask, - lldb::EventSP &event_sp); - std::string m_name; broadcaster_collection m_broadcasters; Mutex m_broadcasters_mutex; // Protects m_broadcasters @@ -191,4 +188,4 @@ private: } // namespace lldb_private -#endif // liblldb_Select_h_ +#endif // liblldb_Select_h_ diff --git a/include/lldb/Core/Log.h b/include/lldb/Core/Log.h index 3aa4b4d48e17..674fdfdfc0b2 100644 --- a/include/lldb/Core/Log.h +++ b/include/lldb/Core/Log.h @@ -182,17 +182,16 @@ private: DISALLOW_COPY_AND_ASSIGN(Log); }; - class LogChannel : public PluginInterface { public: LogChannel(); - virtual ~LogChannel(); + ~LogChannel() override; static lldb::LogChannelSP FindPlugin(const char *plugin_name); - // categories is a an array of chars that ends with a NULL element. + // categories is an array of chars that ends with a NULL element. virtual void Disable(const char **categories, Stream *feedback_strm) = 0; virtual bool Enable( @@ -209,7 +208,6 @@ private: DISALLOW_COPY_AND_ASSIGN(LogChannel); }; - } // namespace lldb_private -#endif // liblldb_Log_H_ +#endif // liblldb_Log_h_ diff --git a/include/lldb/Core/Logging.h b/include/lldb/Core/Logging.h index a4dd76f11237..ca04c84b21a6 100644 --- a/include/lldb/Core/Logging.h +++ b/include/lldb/Core/Logging.h @@ -48,6 +48,7 @@ #define LIBLLDB_LOG_SYSTEM_RUNTIME (1u << 26) #define LIBLLDB_LOG_JIT_LOADER (1u << 27) #define LIBLLDB_LOG_LANGUAGE (1u << 28) +#define LIBLLDB_LOG_DATAFORMATTERS (1u << 29) #define LIBLLDB_LOG_ALL (UINT32_MAX) #define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\ LIBLLDB_LOG_THREAD |\ diff --git a/include/lldb/Core/MappedHash.h b/include/lldb/Core/MappedHash.h index 4b77ff1ab8fc..5a52ab2b8b2d 100644 --- a/include/lldb/Core/MappedHash.h +++ b/include/lldb/Core/MappedHash.h @@ -1,29 +1,38 @@ +//===-- MappedHash.h --------------------------------------------*- C++ -*-===// // -// MappedHash.h +// The LLVM Compiler Infrastructure // +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// #ifndef liblldb_MappedHash_h_ #define liblldb_MappedHash_h_ +// C Includes #include #include +// C++ Includes +#include +#include #include #include +// Other libraries and framework includes +// Project includes #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Stream.h" class MappedHash { public: - enum HashFunctionType { eHashFunctionDJB = 0u // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections }; - static uint32_t HashStringUsingDJB (const char *s) { @@ -50,7 +59,6 @@ public: return 0; } - static const uint32_t HASH_MAGIC = 0x48415348u; static const uint32_t HASH_CIGAM = 0x48534148u; @@ -77,11 +85,9 @@ public: header_data () { } - + virtual - ~Header() - { - } + ~Header() = default; size_t GetByteSize() const @@ -254,8 +260,7 @@ public: header.bucket_count = num_unique_hashes; if (header.bucket_count == 0) header.bucket_count = 1; - - + std::vector hash_buckets; std::vector hash_indexes (header.bucket_count, 0); std::vector hash_values; @@ -345,10 +350,12 @@ public: } } } + protected: typedef std::vector collection; collection m_entries; }; + // A class for reading and using a saved hash table from a block of data // in memory template @@ -375,9 +382,9 @@ public: MemoryTable (lldb_private::DataExtractor &data) : m_header (), - m_hash_indexes (NULL), - m_hash_values (NULL), - m_hash_offsets (NULL) + m_hash_indexes (nullptr), + m_hash_values (nullptr), + m_hash_offsets (nullptr) { lldb::offset_t offset = m_header.Read (data, 0); if (offset != LLDB_INVALID_OFFSET && IsValid ()) @@ -387,12 +394,10 @@ public: m_hash_offsets = (const uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t)); } } - + virtual - ~MemoryTable () - { - } - + ~MemoryTable() = default; + bool IsValid () const { @@ -483,7 +488,6 @@ public: // subclass and return a valie "const char *" given a "key". The value // could also be a C string pointer, in which case just returning "key" // will suffice. - virtual const char * GetStringForKeyType (KeyType key) const = 0; @@ -506,7 +510,6 @@ public: // should be returned. If anything else goes wrong during parsing, // return "eResultError" and the corresponding "Find()" function will // be canceled and return false. - virtual Result GetHashDataForName (const char *name, lldb::offset_t* hash_data_offset_ptr, @@ -518,7 +521,6 @@ public: return m_header; } - void ForEach (std::function const &callback) const { @@ -546,7 +548,6 @@ public: const uint32_t *m_hash_values; const uint32_t *m_hash_offsets; }; - }; -#endif // #ifndef liblldb_MappedHash_h_ +#endif // liblldb_MappedHash_h_ diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h index 127ddaeb9fd4..35b182aa9801 100644 --- a/include/lldb/Core/Module.h +++ b/include/lldb/Core/Module.h @@ -10,6 +10,14 @@ #ifndef liblldb_Module_h_ #define liblldb_Module_h_ +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-forward.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/UUID.h" @@ -17,6 +25,7 @@ #include "lldb/Host/Mutex.h" #include "lldb/Host/TimeValue.h" #include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/PathMappingList.h" namespace lldb_private { @@ -85,11 +94,11 @@ public: /// module within a module (.a files and modules that contain /// multiple architectures). //------------------------------------------------------------------ - Module (const FileSpec& file_spec, - const ArchSpec& arch, - const ConstString *object_name = NULL, - lldb::offset_t object_offset = 0, - const TimeValue *object_mod_time_ptr = NULL); + Module(const FileSpec& file_spec, + const ArchSpec& arch, + const ConstString *object_name = nullptr, + lldb::offset_t object_offset = 0, + const TimeValue *object_mod_time_ptr = nullptr); Module (const ModuleSpec &module_spec); @@ -99,8 +108,7 @@ public: //------------------------------------------------------------------ /// Destructor. //------------------------------------------------------------------ - virtual - ~Module (); + ~Module() override; bool MatchesModuleSpec (const ModuleSpec &module_ref); @@ -154,11 +162,11 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - CalculateSymbolContext (SymbolContext* sc); + void + CalculateSymbolContext(SymbolContext* sc) override; - virtual lldb::ModuleSP - CalculateSymbolContextModule (); + lldb::ModuleSP + CalculateSymbolContextModule() override; void GetDescription (Stream *s, @@ -207,10 +215,9 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - DumpSymbolContext (Stream *s); + void + DumpSymbolContext(Stream *s) override; - //------------------------------------------------------------------ /// Find a symbol in the object file's symbol table. /// @@ -225,7 +232,7 @@ public: /// /// @return /// Returns a valid symbol pointer if a symbol was found, - /// NULL otherwise. + /// nullptr otherwise. //------------------------------------------------------------------ const Symbol * FindFirstSymbolWithNameAndType (const ConstString &name, @@ -288,7 +295,6 @@ public: FindCompileUnits (const FileSpec &path, bool append, SymbolContextList &sc_list); - //------------------------------------------------------------------ /// Find functions by name. @@ -323,7 +329,7 @@ public: //------------------------------------------------------------------ size_t FindFunctions (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool symbols_ok, bool inlines_ok, @@ -392,8 +398,8 @@ public: /// The name of the global or static variable we are looking /// for. /// - /// @param[in] namespace_decl - /// If valid, a namespace to search in. + /// @param[in] parent_decl_ctx + /// If valid, a decl context that results must exist within /// /// @param[in] append /// If \b true, any matches will be appended to \a @@ -413,7 +419,7 @@ public: //------------------------------------------------------------------ size_t FindGlobalVariables (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, VariableList& variable_list); @@ -524,7 +530,7 @@ public: size_t FindTypesInNamespace (const SymbolContext& sc, const ConstString &type_name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, size_t max_matches, TypeList& type_list); @@ -646,10 +652,10 @@ public: IsLoadedInTarget (Target *target); bool - LoadScriptingResourceInTarget (Target *target, - Error& error, - Stream* feedback_stream = NULL); - + LoadScriptingResourceInTarget(Target *target, + Error& error, + Stream* feedback_stream = nullptr); + //------------------------------------------------------------------ /// Get the number of compile units for this module. /// @@ -682,7 +688,7 @@ public: /// @return /// If Module::m_file does not exist, or no plug-in was found /// that can parse the file, or the object file doesn't contain - /// the current architecture in Module::m_arch, NULL will be + /// the current architecture in Module::m_arch, nullptr will be /// returned, else a valid object file interface will be /// returned. The returned pointer is owned by this object and /// remains valid as long as the object is around. @@ -730,7 +736,7 @@ public: /// process. /// /// @return - /// The object file loaded from memory or NULL, if the operation + /// The object file loaded from memory or nullptr, if the operation /// failed (see the `error` for more information in that case). //------------------------------------------------------------------ ObjectFile * @@ -747,20 +753,20 @@ public: /// /// @return /// If this module does not have a valid object file, or no - /// plug-in can be found that can use the object file, NULL will + /// plug-in can be found that can use the object file, nullptr will /// be returned, else a valid symbol vendor plug-in interface /// will be returned. The returned pointer is owned by this /// object and remains valid as long as the object is around. //------------------------------------------------------------------ virtual SymbolVendor* GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = NULL); + lldb_private::Stream *feedback_strm = nullptr); //------------------------------------------------------------------ /// Get accessor the type list for this module. /// /// @return - /// A valid type list pointer, or NULL if there is no valid + /// A valid type list pointer, or nullptr if there is no valid /// symbol vendor for this module. //------------------------------------------------------------------ TypeList* @@ -935,7 +941,6 @@ public: uint32_t ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list); - void SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name); @@ -943,8 +948,8 @@ public: bool GetIsDynamicLinkEditor (); - ClangASTContext & - GetClangASTContext (); + TypeSystem * + GetTypeSystemForLanguage (lldb::LanguageType language); // Special error functions that can do printf style formatting that will prepend the message with // something appropriate for this module (like the architecture, path and object name (if any)). @@ -1041,7 +1046,6 @@ public: bool RemapSourceFile (const char *path, std::string &new_path) const; - //------------------------------------------------------------------ /// Prepare to do a function name lookup. /// @@ -1067,6 +1071,10 @@ public: /// The mask of bits from lldb::FunctionNameType enumerations /// that tell us what kind of name we are looking for. /// + /// @param[out] language + /// If known, the language to use for determining the + /// lookup_name_type_mask. + /// /// @param[out] lookup_name /// The actual name that will be used when calling /// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols() @@ -1087,6 +1095,7 @@ public: static void PrepareForFunctionNameLookup (const ConstString &name, uint32_t name_type_mask, + lldb::LanguageType language, ConstString &lookup_name, uint32_t &lookup_name_type_mask, bool &match_name_after_lookup); @@ -1110,17 +1119,16 @@ protected: lldb::SymbolVendorUP m_symfile_ap; ///< A pointer to the symbol vendor for this module. std::vector m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and changes the symbol file, ///< we need to keep all old symbol files around in case anyone has type references to them - lldb::ClangASTContextUP m_ast; ///< The AST context for this module. + TypeSystemMap m_type_system_map; ///< A map of any type systems associated with this module PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are lldb::SectionListUP m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info - bool m_did_load_objfile:1, - m_did_load_symbol_vendor:1, - m_did_parse_uuid:1, - m_did_init_ast:1; + std::atomic m_did_load_objfile; + std::atomic m_did_load_symbol_vendor; + std::atomic m_did_parse_uuid; mutable bool m_file_has_changed:1, m_first_file_changed_log:1; /// See if the module was modified after it was initially opened. - + //------------------------------------------------------------------ /// Resolve a file or load virtual address. /// @@ -1178,21 +1186,19 @@ protected: friend class SymbolFile; private: - Module (); // Only used internally by CreateJITModule () size_t FindTypes_Impl (const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, - TypeList& types); + TypeMap& types); - DISALLOW_COPY_AND_ASSIGN (Module); }; } // namespace lldb_private -#endif // liblldb_Module_h_ +#endif // liblldb_Module_h_ diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h index f4c12cf168ac..a0dd43263a2c 100644 --- a/include/lldb/Core/ModuleList.h +++ b/include/lldb/Core/ModuleList.h @@ -10,10 +10,14 @@ #ifndef liblldb_ModuleList_h_ #define liblldb_ModuleList_h_ -#include -#include +// C Includes +// C++ Includes #include +#include +#include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/Mutex.h" #include "lldb/Utility/Iterable.h" @@ -30,10 +34,12 @@ namespace lldb_private { class ModuleList { public: - class Notifier { public: + virtual + ~Notifier() = default; + virtual void ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp) = 0; virtual void @@ -43,10 +49,6 @@ public: const lldb::ModuleSP& new_module_sp) = 0; virtual void WillClearList (const ModuleList& module_list) = 0; - - virtual - ~Notifier () - {} }; //------------------------------------------------------------------ @@ -144,6 +146,7 @@ public: //------------------------------------------------------------------ void Destroy(); + //------------------------------------------------------------------ /// Dump the description of each module contained in this list. /// @@ -209,7 +212,7 @@ public: /// An index into this module collection. /// /// @return - /// A pointer to a Module which can by NULL if \a idx is out + /// A pointer to a Module which can by nullptr if \a idx is out /// of range. /// /// @see ModuleList::GetSize() @@ -226,7 +229,7 @@ public: /// An index into this module collection. /// /// @return - /// A pointer to a Module which can by NULL if \a idx is out + /// A pointer to a Module which can by nullptr if \a idx is out /// of range. /// /// @see ModuleList::GetSize() @@ -534,10 +537,10 @@ public: GetSize () const; bool - LoadScriptingResourcesInTarget (Target *target, - std::list& errors, - Stream* feedback_stream = NULL, - bool continue_on_error = true); + LoadScriptingResourcesInTarget(Target *target, + std::list& errors, + Stream* feedback_stream = nullptr, + bool continue_on_error = true); static bool ModuleIsInCache (const Module *module_ptr); @@ -606,9 +609,8 @@ public: { return ModuleIterableNoLocking(m_modules); } - }; } // namespace lldb_private -#endif // liblldb_ModuleList_h_ +#endif // liblldb_ModuleList_h_ diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h index be7041981a0a..95de7f375736 100644 --- a/include/lldb/Core/ModuleSpec.h +++ b/include/lldb/Core/ModuleSpec.h @@ -10,6 +10,12 @@ #ifndef liblldb_ModuleSpec_h_ #define liblldb_ModuleSpec_h_ +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Stream.h" #include "lldb/Core/UUID.h" @@ -100,17 +106,13 @@ public: FileSpec * GetFileSpecPtr () { - if (m_file) - return &m_file; - return NULL; + return (m_file ? &m_file : nullptr); } const FileSpec * GetFileSpecPtr () const { - if (m_file) - return &m_file; - return NULL; + return (m_file ? &m_file : nullptr); } FileSpec & @@ -118,6 +120,7 @@ public: { return m_file; } + const FileSpec & GetFileSpec () const { @@ -127,17 +130,13 @@ public: FileSpec * GetPlatformFileSpecPtr () { - if (m_platform_file) - return &m_platform_file; - return NULL; + return (m_platform_file ? &m_platform_file : nullptr); } const FileSpec * GetPlatformFileSpecPtr () const { - if (m_platform_file) - return &m_platform_file; - return NULL; + return (m_platform_file ? &m_platform_file : nullptr); } FileSpec & @@ -155,17 +154,13 @@ public: FileSpec * GetSymbolFileSpecPtr () { - if (m_symbol_file) - return &m_symbol_file; - return NULL; + return (m_symbol_file ? &m_symbol_file : nullptr); } const FileSpec * GetSymbolFileSpecPtr () const { - if (m_symbol_file) - return &m_symbol_file; - return NULL; + return (m_symbol_file ? &m_symbol_file : nullptr); } FileSpec & @@ -180,21 +175,16 @@ public: return m_symbol_file; } - ArchSpec * GetArchitecturePtr () { - if (m_arch.IsValid()) - return &m_arch; - return NULL; + return (m_arch.IsValid() ? &m_arch : nullptr); } const ArchSpec * GetArchitecturePtr () const { - if (m_arch.IsValid()) - return &m_arch; - return NULL; + return (m_arch.IsValid() ? &m_arch : nullptr); } ArchSpec & @@ -212,17 +202,13 @@ public: UUID * GetUUIDPtr () { - if (m_uuid.IsValid()) - return &m_uuid; - return NULL; + return (m_uuid.IsValid() ? &m_uuid : nullptr); } const UUID * GetUUIDPtr () const { - if (m_uuid.IsValid()) - return &m_uuid; - return NULL; + return (m_uuid.IsValid() ? &m_uuid : nullptr); } UUID & @@ -306,7 +292,6 @@ public: m_object_mod_time.Clear(); } - explicit operator bool () const { if (m_file) @@ -329,7 +314,7 @@ public: } void - Dump (Stream &strm) + Dump (Stream &strm) const { bool dumped_something = false; if (m_file) @@ -361,7 +346,8 @@ public: { if (dumped_something) strm.PutCString(", "); - strm.Printf("arch = %s", m_arch.GetTriple().str().c_str()); + strm.Printf("arch = "); + m_arch.DumpTriple(strm); dumped_something = true; } if (m_uuid.IsValid()) @@ -476,9 +462,7 @@ public: m_specs = rhs.m_specs; } - ~ModuleSpecList () - { - } + ~ModuleSpecList() = default; ModuleSpecList & operator = (const ModuleSpecList &rhs) @@ -528,6 +512,7 @@ public: { return m_specs[i]; } + bool GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const { @@ -540,8 +525,7 @@ public: module_spec.Clear(); return false; } - - + bool FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const { @@ -620,4 +604,4 @@ protected: } // namespace lldb_private -#endif // liblldb_ModuleSpec_h_ +#endif // liblldb_ModuleSpec_h_ diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h index 57b8077477ce..eac0746baba1 100644 --- a/include/lldb/Core/Opcode.h +++ b/include/lldb/Core/Opcode.h @@ -16,6 +16,7 @@ // C++ Includes // Other libraries and framework includes #include "llvm/Support/MathExtras.h" + // Project includes #include "lldb/Host/Endian.h" #include "lldb/lldb-public.h" @@ -23,7 +24,7 @@ namespace lldb { class SBInstruction; -} +} // namespace lldb namespace lldb_private { @@ -76,6 +77,7 @@ namespace lldb_private { m_byte_order = lldb::eByteOrderInvalid; m_type = Opcode::eTypeInvalid; } + Opcode::Type GetType () const { @@ -189,7 +191,7 @@ namespace lldb_private { void SetOpcodeBytes (const void *bytes, size_t length) { - if (bytes && length > 0) + if (bytes != nullptr && length > 0) { m_type = eTypeBytes; m_data.inst.length = length; @@ -210,9 +212,7 @@ namespace lldb_private { const void * GetOpcodeBytes () const { - if (m_type == Opcode::eTypeBytes) - return m_data.inst.bytes; - return NULL; + return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr); } uint32_t @@ -252,7 +252,7 @@ namespace lldb_private { case Opcode::eType64: return &m_data.inst64; case Opcode::eTypeBytes: return m_data.inst.bytes; } - return NULL; + return nullptr; } lldb::ByteOrder @@ -261,8 +261,8 @@ namespace lldb_private { bool GetEndianSwap() const { - return (m_byte_order == lldb::eByteOrderBig && lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) || - (m_byte_order == lldb::eByteOrderLittle && lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig); + return (m_byte_order == lldb::eByteOrderBig && endian::InlHostByteOrder() == lldb::eByteOrderLittle) || + (m_byte_order == lldb::eByteOrderLittle && endian::InlHostByteOrder() == lldb::eByteOrderBig); } lldb::ByteOrder m_byte_order; @@ -284,4 +284,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // lldb_Opcode_h +#endif // lldb_Opcode_h diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h index af940d788ab0..6f8001fbfd2b 100644 --- a/include/lldb/Core/PluginManager.h +++ b/include/lldb/Core/PluginManager.h @@ -7,10 +7,13 @@ // //===----------------------------------------------------------------------===// - #ifndef liblldb_PluginManager_h_ #define liblldb_PluginManager_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/FileSpec.h" @@ -42,7 +45,6 @@ public: static ABICreateInstance GetABICreateCallbackForPluginName (const ConstString &name); - //------------------------------------------------------------------ // Disassembler //------------------------------------------------------------------ @@ -60,15 +62,14 @@ public: static DisassemblerCreateInstance GetDisassemblerCreateCallbackForPluginName (const ConstString &name); - //------------------------------------------------------------------ // DynamicLoader //------------------------------------------------------------------ static bool - RegisterPlugin (const ConstString &name, - const char *description, - DynamicLoaderCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback = NULL); + RegisterPlugin(const ConstString &name, + const char *description, + DynamicLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin (DynamicLoaderCreateInstance create_callback); @@ -83,10 +84,10 @@ public: // JITLoader //------------------------------------------------------------------ static bool - RegisterPlugin (const ConstString &name, - const char *description, - JITLoaderCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback = NULL); + RegisterPlugin(const ConstString &name, + const char *description, + JITLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin (JITLoaderCreateInstance create_callback); @@ -117,11 +118,10 @@ public: //------------------------------------------------------------------ // OperatingSystem //------------------------------------------------------------------ - static bool - RegisterPlugin (const ConstString &name, - const char *description, - OperatingSystemCreateInstance create_callback); - + static bool RegisterPlugin(const ConstString &name, const char *description, + OperatingSystemCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback); + static bool UnregisterPlugin (OperatingSystemCreateInstance create_callback); @@ -131,6 +131,23 @@ public: static OperatingSystemCreateInstance GetOperatingSystemCreateCallbackForPluginName (const ConstString &name); + //------------------------------------------------------------------ + // Language + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + LanguageCreateInstance create_callback); + + static bool + UnregisterPlugin (LanguageCreateInstance create_callback); + + static LanguageCreateInstance + GetLanguageCreateCallbackAtIndex (uint32_t idx); + + static LanguageCreateInstance + GetLanguageCreateCallbackForPluginName (const ConstString &name); + //------------------------------------------------------------------ // LanguageRuntime //------------------------------------------------------------------ @@ -152,7 +169,6 @@ public: static LanguageRuntimeCreateInstance GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name); - //------------------------------------------------------------------ // SystemRuntime //------------------------------------------------------------------ @@ -170,17 +186,16 @@ public: static SystemRuntimeCreateInstance GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name); - //------------------------------------------------------------------ // ObjectFile //------------------------------------------------------------------ static bool - RegisterPlugin (const ConstString &name, - const char *description, - ObjectFileCreateInstance create_callback, - ObjectFileCreateMemoryInstance create_memory_callback, - ObjectFileGetModuleSpecifications get_module_specifications, - ObjectFileSaveCore save_core = NULL); + RegisterPlugin(const ConstString &name, + const char *description, + ObjectFileCreateInstance create_callback, + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectFileSaveCore save_core = nullptr); static bool UnregisterPlugin (ObjectFileCreateInstance create_callback); @@ -248,10 +263,10 @@ public: // Platform //------------------------------------------------------------------ static bool - RegisterPlugin (const ConstString &name, - const char *description, - PlatformCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback = NULL); + RegisterPlugin(const ConstString &name, + const char *description, + PlatformCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin (PlatformCreateInstance create_callback); @@ -275,10 +290,10 @@ public: // Process //------------------------------------------------------------------ static bool - RegisterPlugin (const ConstString &name, - const char *description, - ProcessCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback = NULL); + RegisterPlugin(const ConstString &name, + const char *description, + ProcessCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin (ProcessCreateInstance create_callback); @@ -295,13 +310,31 @@ public: static const char * GetProcessPluginDescriptionAtIndex (uint32_t idx); + //------------------------------------------------------------------ + // ScriptInterpreter + //------------------------------------------------------------------ + static bool + RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_lang, + ScriptInterpreterCreateInstance create_callback); + + static bool + UnregisterPlugin(ScriptInterpreterCreateInstance create_callback); + + static ScriptInterpreterCreateInstance + GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx); + + static lldb::ScriptInterpreterSP + GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, + CommandInterpreter &interpreter); + //------------------------------------------------------------------ // SymbolFile //------------------------------------------------------------------ static bool RegisterPlugin (const ConstString &name, const char *description, - SymbolFileCreateInstance create_callback); + SymbolFileCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin (SymbolFileCreateInstance create_callback); @@ -312,7 +345,6 @@ public: static SymbolFileCreateInstance GetSymbolFileCreateCallbackForPluginName (const ConstString &name); - //------------------------------------------------------------------ // SymbolVendor //------------------------------------------------------------------ @@ -385,6 +417,53 @@ public: static InstrumentationRuntimeCreateInstance GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name); + //------------------------------------------------------------------ + // TypeSystem + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + TypeSystemCreateInstance create_callback, + TypeSystemEnumerateSupportedLanguages enumerate_languages_callback); + + static bool + UnregisterPlugin (TypeSystemCreateInstance create_callback); + + static TypeSystemCreateInstance + GetTypeSystemCreateCallbackAtIndex (uint32_t idx); + + static TypeSystemCreateInstance + GetTypeSystemCreateCallbackForPluginName (const ConstString &name); + + static TypeSystemEnumerateSupportedLanguages + GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx); + + static TypeSystemEnumerateSupportedLanguages + GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // REPL + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + REPLCreateInstance create_callback, + REPLEnumerateSupportedLanguages enumerate_languages_callback); + + static bool + UnregisterPlugin (REPLCreateInstance create_callback); + + static REPLCreateInstance + GetREPLCreateCallbackAtIndex (uint32_t idx); + + static REPLCreateInstance + GetREPLCreateCallbackForPluginName (const ConstString &name); + + static REPLEnumerateSupportedLanguages + GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx); + + static REPLEnumerateSupportedLanguages + GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name); //------------------------------------------------------------------ // Some plug-ins might register a DebuggerInitializeCallback @@ -419,16 +498,41 @@ public: static lldb::OptionValuePropertiesSP GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name); - + static bool CreateSettingForProcessPlugin (Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, const ConstString &description, bool is_global_property); -}; + static lldb::OptionValuePropertiesSP + GetSettingForSymbolFilePlugin (Debugger &debugger, + const ConstString &setting_name); + + static bool + CreateSettingForSymbolFilePlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForJITLoaderPlugin (Debugger &debugger, + const ConstString &setting_name); + static bool + CreateSettingForJITLoaderPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); + + static lldb::OptionValuePropertiesSP GetSettingForOperatingSystemPlugin(Debugger &debugger, + const ConstString &setting_name); + + static bool CreateSettingForOperatingSystemPlugin(Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property); +}; } // namespace lldb_private -#endif // liblldb_PluginManager_h_ +#endif // liblldb_PluginManager_h_ diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h index d2c43a5d794d..b2e3f06f08a9 100644 --- a/include/lldb/Core/RangeMap.h +++ b/include/lldb/Core/RangeMap.h @@ -10,16 +10,21 @@ #ifndef liblldb_RangeMap_h_ #define liblldb_RangeMap_h_ +// C Includes +// C++ Includes +#include #include -#include "lldb/lldb-private.h" +// 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 //#define ASSERT_RANGEMAP_ARE_SORTED namespace lldb_private { - //---------------------------------------------------------------------- // Templatized classes for dealing with generic ranges and also @@ -187,16 +192,11 @@ namespace lldb_private { typedef S SizeType; typedef Range Entry; typedef llvm::SmallVector Collection; - - RangeArray () : - m_entries () - { - } - - ~RangeArray() - { - } - + + RangeArray() = default; + + ~RangeArray() = default; + void Append (const Entry &entry) { @@ -236,6 +236,7 @@ namespace lldb_private { return true; } #endif + void CombineConsecutiveRanges () { @@ -281,7 +282,6 @@ namespace lldb_private { } } - BaseType GetMinRangeBase (BaseType fail_value) const { @@ -337,9 +337,7 @@ namespace lldb_private { const Entry * GetEntryAtIndex (size_t i) const { - if (i Entry; typedef std::vector Collection; - - RangeVector () : - m_entries () - { - } - - ~RangeVector() - { - } - + + RangeVector() = default; + + ~RangeVector() = default; + void Append (const Entry &entry) { @@ -516,6 +505,7 @@ namespace lldb_private { return true; } #endif + void CombineConsecutiveRanges () { @@ -560,8 +550,7 @@ namespace lldb_private { } } } - - + BaseType GetMinRangeBase (BaseType fail_value) const { @@ -623,9 +612,7 @@ namespace lldb_private { const Entry * GetEntryAtIndex (size_t i) const { - if (i Entry; typedef llvm::SmallVector Collection; + RangeDataArray() = default; + + ~RangeDataArray() = default; - RangeDataArray () - { - } - - ~RangeDataArray() - { - } - void Append (const Entry &entry) { @@ -911,9 +889,7 @@ namespace lldb_private { const Entry * GetEntryAtIndex (size_t i) const { - if (i Entry; typedef std::vector Collection; - - RangeDataVector () - { - } - - ~RangeDataVector() - { - } - + + RangeDataVector() = default; + + ~RangeDataVector() = default; + void Append (const Entry &entry) { @@ -1181,7 +1150,6 @@ namespace lldb_private { } } } - } void @@ -1211,9 +1179,7 @@ namespace lldb_private { const Entry * GetEntryAtIndex (size_t i) const { - if (iContains(addr)) return &(*pos); } - return NULL; + return nullptr; } + const Entry * FindEntryThatContains (B addr) const { @@ -1295,7 +1262,7 @@ namespace lldb_private { if (pos != end && pos->Contains(addr)) return &(*pos); } - return NULL; + return nullptr; } const Entry * @@ -1316,30 +1283,25 @@ namespace lldb_private { if (pos != end && pos->Contains(range)) return &(*pos); } - return NULL; + return nullptr; } Entry * Back() { - if (!m_entries.empty()) - return &m_entries.back(); - return NULL; + return (m_entries.empty() ? nullptr : &m_entries.back()); } const Entry * Back() const { - if (!m_entries.empty()) - return &m_entries.back(); - return NULL; + return (m_entries.empty() ? nullptr : &m_entries.back()); } protected: Collection m_entries; }; - - + //---------------------------------------------------------------------- // A simple range with data class where you get to define the type of // the range base "B", the type used for the range byte size "S", and @@ -1389,7 +1351,6 @@ namespace lldb_private { } }; - template class AddressDataArray { @@ -1397,15 +1358,10 @@ namespace lldb_private { typedef AddressData Entry; typedef llvm::SmallVector Collection; + AddressDataArray() = default; + + ~AddressDataArray() = default; - AddressDataArray () - { - } - - ~AddressDataArray() - { - } - void Append (const Entry &entry) { @@ -1456,9 +1412,7 @@ namespace lldb_private { const Entry * GetEntryAtIndex (size_t i) const { - if (i= &*m_entries.begin() && entry + 1 < &*m_entries.end()) return entry + 1; - return NULL; + return nullptr; } Entry * Back() { - if (!m_entries.empty()) - return &m_entries.back(); - return NULL; + return (m_entries.empty() ? nullptr : &m_entries.back()); } const Entry * Back() const { - if (!m_entries.empty()) - return &m_entries.back(); - return NULL; + return (m_entries.empty() ? nullptr : &m_entries.back()); } protected: @@ -1530,4 +1480,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // liblldb_RangeMap_h_ +#endif // liblldb_RangeMap_h_ diff --git a/include/lldb/Core/RegisterValue.h b/include/lldb/Core/RegisterValue.h index 1b1a71a11c5a..030b849212c4 100644 --- a/include/lldb/Core/RegisterValue.h +++ b/include/lldb/Core/RegisterValue.h @@ -1,4 +1,4 @@ -//===-- RegisterValue.h ------------------------------------------*- C++ -*-===// +//===-- RegisterValue.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,12 +15,14 @@ // C++ Includes // Other libraries and framework includes +#include "llvm/ADT/APInt.h" + // Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-private.h" #include "lldb/Host/Endian.h" +#include "lldb/Core/Scalar.h" -//#define ENABLE_128_BIT_SUPPORT 1 namespace lldb_private { class RegisterValue @@ -30,6 +32,7 @@ namespace lldb_private { { kMaxRegisterByteSize = 32u }; + enum Type { eTypeInvalid, @@ -37,9 +40,7 @@ namespace lldb_private { eTypeUInt16, eTypeUInt32, eTypeUInt64, -#if defined (ENABLE_128_BIT_SUPPORT) eTypeUInt128, -#endif eTypeFloat, eTypeDouble, eTypeLongDouble, @@ -47,7 +48,8 @@ namespace lldb_private { }; RegisterValue () : - m_type (eTypeInvalid) + m_type (eTypeInvalid), + m_scalar ((unsigned long)0) { } @@ -55,57 +57,56 @@ namespace lldb_private { RegisterValue (uint8_t inst) : m_type (eTypeUInt8) { - m_data.uint8 = inst; + m_scalar = inst; } explicit RegisterValue (uint16_t inst) : m_type (eTypeUInt16) { - m_data.uint16 = inst; + m_scalar = inst; } explicit RegisterValue (uint32_t inst) : m_type (eTypeUInt32) { - m_data.uint32 = inst; + m_scalar = inst; } explicit RegisterValue (uint64_t inst) : m_type (eTypeUInt64) { - m_data.uint64 = inst; + m_scalar = inst; } -#if defined (ENABLE_128_BIT_SUPPORT) explicit - RegisterValue (__uint128_t inst) : + RegisterValue (llvm::APInt inst) : m_type (eTypeUInt128) { - m_data.uint128 = inst; + m_scalar = llvm::APInt(inst); } -#endif + explicit RegisterValue (float value) : m_type (eTypeFloat) { - m_data.ieee_float = value; + m_scalar = value; } explicit RegisterValue (double value) : m_type (eTypeDouble) { - m_data.ieee_double = value; + m_scalar = value; } explicit RegisterValue (long double value) : m_type (eTypeLongDouble) { - m_data.ieee_long_double = value; + m_scalar = value; } explicit @@ -161,13 +162,13 @@ namespace lldb_private { GetScalarValue (Scalar &scalar) const; uint8_t - GetAsUInt8 (uint8_t fail_value = UINT8_MAX, bool *success_ptr = NULL) const + GetAsUInt8(uint8_t fail_value = UINT8_MAX, bool *success_ptr = nullptr) const { if (m_type == eTypeUInt8) { if (success_ptr) *success_ptr = true; - return m_data.uint8; + return m_scalar.UChar(fail_value); } if (success_ptr) *success_ptr = true; @@ -175,27 +176,25 @@ namespace lldb_private { } uint16_t - GetAsUInt16 (uint16_t fail_value = UINT16_MAX, bool *success_ptr = NULL) const; + GetAsUInt16(uint16_t fail_value = UINT16_MAX, bool *success_ptr = nullptr) const; uint32_t - GetAsUInt32 (uint32_t fail_value = UINT32_MAX, bool *success_ptr = NULL) const; + GetAsUInt32(uint32_t fail_value = UINT32_MAX, bool *success_ptr = nullptr) const; uint64_t - GetAsUInt64 (uint64_t fail_value = UINT64_MAX, bool *success_ptr = NULL) const; + GetAsUInt64(uint64_t fail_value = UINT64_MAX, bool *success_ptr = nullptr) const; -#if defined (ENABLE_128_BIT_SUPPORT) - __uint128_t - GetAsUInt128 (__uint128_t fail_value = ~((__uint128_t)0), bool *success_ptr = NULL) const; -#endif + llvm::APInt + GetAsUInt128(const llvm::APInt& fail_value, bool *success_ptr = nullptr) const; float - GetAsFloat (float fail_value = 0.0f, bool *success_ptr = NULL) const; + GetAsFloat(float fail_value = 0.0f, bool *success_ptr = nullptr) const; double - GetAsDouble (double fail_value = 0.0, bool *success_ptr = NULL) const; + GetAsDouble(double fail_value = 0.0, bool *success_ptr = nullptr) const; long double - GetAsLongDouble (long double fail_value = 0.0, bool *success_ptr = NULL) const; + GetAsLongDouble(long double fail_value = 0.0, bool *success_ptr = nullptr) const; void SetValueToInvalid () @@ -219,95 +218,93 @@ namespace lldb_private { operator = (uint8_t uint) { m_type = eTypeUInt8; - m_data.uint8 = uint; + m_scalar = uint; } void operator = (uint16_t uint) { m_type = eTypeUInt16; - m_data.uint16 = uint; + m_scalar = uint; } void operator = (uint32_t uint) { m_type = eTypeUInt32; - m_data.uint32 = uint; + m_scalar = uint; } void operator = (uint64_t uint) { m_type = eTypeUInt64; - m_data.uint64 = uint; + m_scalar = uint; } -#if defined (ENABLE_128_BIT_SUPPORT) void - operator = (__uint128_t uint) + operator = (llvm::APInt uint) { m_type = eTypeUInt128; - m_data.uint128 = uint; + m_scalar = llvm::APInt(uint); } -#endif + void operator = (float f) { m_type = eTypeFloat; - m_data.ieee_float = f; + m_scalar = f; } void operator = (double f) { m_type = eTypeDouble; - m_data.ieee_double = f; + m_scalar = f; } void operator = (long double f) { m_type = eTypeLongDouble; - m_data.ieee_long_double = f; + m_scalar = f; } void SetUInt8 (uint8_t uint) { m_type = eTypeUInt8; - m_data.uint8 = uint; + m_scalar = uint; } void SetUInt16 (uint16_t uint) { m_type = eTypeUInt16; - m_data.uint16 = uint; + m_scalar = uint; } void SetUInt32 (uint32_t uint, Type t = eTypeUInt32) { m_type = t; - m_data.uint32 = uint; + m_scalar = uint; } void SetUInt64 (uint64_t uint, Type t = eTypeUInt64) { m_type = t; - m_data.uint64 = uint; + m_scalar = uint; } -#if defined (ENABLE_128_BIT_SUPPORT) void - SetUInt128 (__uint128_t uint) + SetUInt128 (llvm::APInt uint) { m_type = eTypeUInt128; - m_data.uint128 = uint; + m_scalar = uint; } -#endif + bool SetUInt (uint64_t uint, uint32_t byte_size); @@ -315,21 +312,21 @@ namespace lldb_private { SetFloat (float f) { m_type = eTypeFloat; - m_data.ieee_float = f; + m_scalar = f; } void SetDouble (double f) { m_type = eTypeDouble; - m_data.ieee_double = f; + m_scalar = f; } void SetLongDouble (long double f) { m_type = eTypeLongDouble; - m_data.ieee_long_double = f; + m_scalar = f; } void @@ -367,8 +364,8 @@ namespace lldb_private { GetByteOrder () const { if (m_type == eTypeBytes) - return m_data.buffer.byte_order; - return lldb::endian::InlHostByteOrder(); + return buffer.byte_order; + return endian::InlHostByteOrder(); } uint32_t @@ -384,29 +381,17 @@ namespace lldb_private { Clear(); protected: - RegisterValue::Type m_type; - union - { - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; -#if defined (ENABLE_128_BIT_SUPPORT) - __uint128_t uint128; -#endif - float ieee_float; - double ieee_double; - long double ieee_long_double; - struct - { - uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any register for any supported target. - uint8_t length; - lldb::ByteOrder byte_order; - } buffer; - } m_data; + Scalar m_scalar; + + struct + { + uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any register for any supported target. + uint8_t length; + lldb::ByteOrder byte_order; + } buffer; }; } // namespace lldb_private -#endif // lldb_RegisterValue_h +#endif // lldb_RegisterValue_h diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h index a58d17b4a794..b0ece5154ce1 100644 --- a/include/lldb/Core/RegularExpression.h +++ b/include/lldb/Core/RegularExpression.h @@ -7,9 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DBRegex_h_ -#define liblldb_DBRegex_h_ -#if defined(__cplusplus) +#ifndef liblldb_RegularExpression_h_ +#define liblldb_RegularExpression_h_ #ifdef _WIN32 #include "../lib/Support/regex_impl.h" @@ -37,7 +36,6 @@ inline void regfree(llvm_regex_t * a) { llvm_regfree(a); } - #else #if __ANDROID_NDK__ #include @@ -52,7 +50,7 @@ inline void regfree(llvm_regex_t * a) namespace llvm { class StringRef; -} +} // namespace llvm namespace lldb_private { @@ -95,9 +93,7 @@ public: regmatch_t * GetData () { - if (m_matches.empty()) - return NULL; - return m_matches.data(); + return (m_matches.empty() ? nullptr : m_matches.data()); } bool @@ -110,9 +106,9 @@ public: GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const; protected: - std::vector m_matches; ///< Where parenthesized subexpressions results are stored }; + //------------------------------------------------------------------ /// Default constructor. /// @@ -172,14 +168,14 @@ public: /// @param[in] match /// A pointer to a RegularExpression::Match structure that was /// properly initialized with the desired number of maximum - /// matches, or NULL if no parenthesized matching is needed. + /// matches, or nullptr if no parenthesized matching is needed. /// /// @return /// \b true if \a string matches the compiled regular /// expression, \b false otherwise. //------------------------------------------------------------------ bool - Execute (const char* string, Match *match = NULL) const; + Execute(const char* string, Match *match = nullptr) const; size_t GetErrorAsCString (char *err_str, size_t err_str_max_len) const; @@ -246,5 +242,4 @@ private: } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_DBRegex_h_ +#endif // liblldb_RegularExpression_h_ diff --git a/include/lldb/Core/STLUtils.h b/include/lldb/Core/STLUtils.h index 9321e057a397..b3c2124f447d 100644 --- a/include/lldb/Core/STLUtils.h +++ b/include/lldb/Core/STLUtils.h @@ -9,14 +9,18 @@ #ifndef liblldb_STLUtils_h_ #define liblldb_STLUtils_h_ -#if defined(__cplusplus) +// C Includes #include +// C++ Includes #include #include #include +// Other libraries and framework includes +// Project includes + //---------------------------------------------------------------------- // C string less than compare function object //---------------------------------------------------------------------- @@ -28,7 +32,6 @@ struct CStringCompareFunctionObject } }; - //---------------------------------------------------------------------- // C string equality function object (binary predicate). //---------------------------------------------------------------------- @@ -40,7 +43,6 @@ struct CStringEqualBinaryPredicate } }; - //---------------------------------------------------------------------- // Templated type for finding an entry in a std::map whose value // is equal to something @@ -48,21 +50,26 @@ struct CStringEqualBinaryPredicate template class ValueEquals { -private: - S second_value; - public: ValueEquals (const S& val) : second_value(val) {} + // Compare the second item bool operator() (std::pair elem) { return elem.second == second_value; } + +private: + S second_value; }; template -inline void PrintAllCollectionElements (std::ostream &s, const T& coll, const char* header_cstr=NULL, const char* separator_cstr=" ") +inline void +PrintAllCollectionElements(std::ostream &s, + const T& coll, + const char* header_cstr = nullptr, + const char* separator_cstr = " ") { typename T::const_iterator pos; @@ -88,7 +95,4 @@ struct for_each_cplusplus_delete typedef std::vector STLStringArray; typedef std::vector CStringArray; - - -#endif // #if defined(__cplusplus) -#endif // liblldb_STLUtils_h_ +#endif // liblldb_STLUtils_h_ diff --git a/include/lldb/Core/Scalar.h b/include/lldb/Core/Scalar.h index 821a0fb1ae21..a476cd3bd867 100644 --- a/include/lldb/Core/Scalar.h +++ b/include/lldb/Core/Scalar.h @@ -11,6 +11,11 @@ #define liblldb_Scalar_h_ #include "lldb/lldb-private.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" + +#define NUM_OF_WORDS_INT128 2 +#define BITWIDTH_INT128 128 namespace lldb_private { @@ -34,22 +39,60 @@ public: e_ulonglong, e_float, e_double, - e_long_double + e_long_double, + e_uint128, + e_sint128 }; //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ Scalar(); - Scalar(int v) : m_type(e_sint), m_data() { m_data.sint = v; } - Scalar(unsigned int v) : m_type(e_uint), m_data() { m_data.uint = v; } - Scalar(long v) : m_type(e_slong), m_data() { m_data.slong = v; } - Scalar(unsigned long v) : m_type(e_ulong), m_data() { m_data.ulong = v; } - Scalar(long long v) : m_type(e_slonglong), m_data() { m_data.slonglong = v; } - Scalar(unsigned long long v): m_type(e_ulonglong), m_data() { m_data.ulonglong = v; } - Scalar(float v) : m_type(e_float), m_data() { m_data.flt = v; } - Scalar(double v) : m_type(e_double), m_data() { m_data.dbl = v; } - Scalar(long double v) : m_type(e_long_double), m_data() { m_data.ldbl = v; } + Scalar(int v) : m_type(e_sint), m_float((float)0) { m_integer = llvm::APInt(sizeof(int) * 8, v, true);} + Scalar(unsigned int v) : m_type(e_uint), m_float((float)0) { m_integer = llvm::APInt(sizeof(int) * 8, v);} + Scalar(long v) : m_type(e_slong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long) * 8, v, true);} + Scalar(unsigned long v) : m_type(e_ulong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long) * 8, v);} + Scalar(long long v) : m_type(e_slonglong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long long) * 8, v, true);} + Scalar(unsigned long long v): m_type(e_ulonglong), m_float((float)0) { m_integer = llvm::APInt(sizeof(long long) * 8, v);} + Scalar(float v) : m_type(e_float), m_float(v) { m_float = llvm::APFloat(v); } + Scalar(double v) : m_type(e_double), m_float(v) { m_float = llvm::APFloat(v); } + Scalar(long double v, bool ieee_quad) + : m_type(e_long_double), m_float((float)0), m_ieee_quad(ieee_quad) + { + if(ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + } + Scalar(llvm::APInt v) : + m_type(), + m_float((float)0) + { + m_integer = llvm::APInt(v); + switch(m_integer.getBitWidth()) + { + case 8: + case 16: + case 32: + if(m_integer.isSignedIntN(sizeof(sint_t) * 8)) + m_type = e_sint; + else + m_type = e_uint; + break; + case 64: + if(m_integer.isSignedIntN(sizeof(slonglong_t) * 8)) + m_type = e_slonglong; + else + m_type = e_ulonglong; + break; + case 128: + if(m_integer.isSignedIntN(BITWIDTH_INT128)) + m_type = e_sint128; + else + m_type = e_uint128; + break; + } + } Scalar(const Scalar& rhs); //Scalar(const RegisterValue& reg_value); virtual ~Scalar(); @@ -61,15 +104,18 @@ public: ExtractBitfield (uint32_t bit_size, uint32_t bit_offset); + bool + SetBit(uint32_t bit); + + bool + ClearBit(uint32_t bit); + + void * + GetBytes() const; + size_t GetByteSize() const; - static size_t - GetMaxByteSize() - { - return sizeof(ValueData); - } - bool GetData (DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const; @@ -83,7 +129,7 @@ public: IsZero() const; void - Clear() { m_type = e_void; m_data.ulonglong = 0; } + Clear() { m_type = e_void; m_integer.clearAllBits(); } const char * GetTypeAsCString() const; @@ -133,6 +179,7 @@ public: Scalar& operator= (float v); Scalar& operator= (double v); Scalar& operator= (long double v); + Scalar& operator= (llvm::APInt v); Scalar& operator= (const Scalar& rhs); // Assignment operator Scalar& operator+= (const Scalar& rhs); Scalar& operator<<= (const Scalar& rhs); // Shift left @@ -174,6 +221,9 @@ public: Scalar::Type GetType() const { return m_type; } + void + SetType(const RegisterInfo*); + //---------------------------------------------------------------------- // Returns a casted value of the current contained data without // modifying the current value. FAIL_VALUE will be returned if the type @@ -194,6 +244,18 @@ public: unsigned long long RawULongLong () const; + unsigned char + UChar(unsigned char fail_value = 0) const; + + char + SChar(char fail_value = 0) const; + + unsigned short + UShort(unsigned short fail_value = 0) const; + + short + SShort(short fail_value = 0) const; + unsigned int UInt(unsigned int fail_value = 0) const; @@ -209,6 +271,12 @@ public: unsigned long long ULongLong(unsigned long long fail_value = 0) const; + llvm::APInt + SInt128(llvm::APInt& fail_value) const; + + llvm::APInt + UInt128(const llvm::APInt& fail_value) const; + float Float(float fail_value = 0.0f) const; @@ -255,6 +323,10 @@ public: } protected: + typedef char schar_t; + typedef unsigned char uchar_t; + typedef short sshort_t; + typedef unsigned short ushort_t; typedef int sint_t; typedef unsigned int uint_t; typedef long slong_t; @@ -265,24 +337,13 @@ protected: typedef double double_t; typedef long double long_double_t; - union ValueData - { - int sint; - unsigned int uint; - long slong; - unsigned long ulong; - long long slonglong; - unsigned long long ulonglong; - float flt; - double dbl; - long double ldbl; - }; - //------------------------------------------------------------------ // Classes that inherit from Scalar can see and modify these //------------------------------------------------------------------ Scalar::Type m_type; - ValueData m_data; + llvm::APInt m_integer; + llvm::APFloat m_float; + bool m_ieee_quad = false; private: friend const Scalar operator+ (const Scalar& lhs, const Scalar& rhs); diff --git a/include/lldb/Core/SearchFilter.h b/include/lldb/Core/SearchFilter.h index bbb7509cedb2..3d5e1fb39b43 100644 --- a/include/lldb/Core/SearchFilter.h +++ b/include/lldb/Core/SearchFilter.h @@ -272,7 +272,7 @@ class SearchFilterForUnconstrainedSearches : { public: SearchFilterForUnconstrainedSearches (const lldb::TargetSP &target_sp) : SearchFilter(target_sp) {} - ~SearchFilterForUnconstrainedSearches () {} + ~SearchFilterForUnconstrainedSearches() override = default; bool ModulePasses (const FileSpec &module_spec) override; @@ -283,7 +283,6 @@ public: protected: lldb::SearchFilterSP DoCopyForBreakpoint (Breakpoint &breakpoint) override; - }; //---------------------------------------------------------------------- @@ -311,8 +310,7 @@ public: SearchFilterByModule (const SearchFilterByModule& rhs); - virtual - ~SearchFilterByModule (); + ~SearchFilterByModule() override; const SearchFilterByModule& operator=(const SearchFilterByModule& rhs); @@ -372,8 +370,7 @@ public: SearchFilterByModuleList (const SearchFilterByModuleList& rhs); - virtual - ~SearchFilterByModuleList (); + ~SearchFilterByModuleList() override; const SearchFilterByModuleList& operator=(const SearchFilterByModuleList& rhs); @@ -409,7 +406,7 @@ protected: lldb::SearchFilterSP DoCopyForBreakpoint (Breakpoint &breakpoint) override; -private: +protected: FileSpecList m_module_spec_list; }; @@ -434,8 +431,7 @@ public: SearchFilterByModuleListAndCU (const SearchFilterByModuleListAndCU& rhs); - virtual - ~SearchFilterByModuleListAndCU (); + ~SearchFilterByModuleListAndCU() override; const SearchFilterByModuleListAndCU& operator=(const SearchFilterByModuleListAndCU& rhs); @@ -466,10 +462,9 @@ protected: DoCopyForBreakpoint (Breakpoint &breakpoint) override; private: - FileSpecList m_module_spec_list; FileSpecList m_cu_spec_list; }; } // namespace lldb_private -#endif // liblldb_SearchFilter_h_ +#endif // liblldb_SearchFilter_h_ diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h index 65d408e29867..8c92f1ba667e 100644 --- a/include/lldb/Core/Section.h +++ b/include/lldb/Core/Section.h @@ -64,9 +64,6 @@ public: lldb::SectionSP FindSectionContainingFileAddress (lldb::addr_t addr, uint32_t depth = UINT32_MAX) const; - bool - GetSectionData (const DataExtractor& module_data, DataExtractor& section_data) const; - // Get the number of sections in this list only size_t GetSize () const @@ -288,6 +285,46 @@ public: return m_obj_file; } + //------------------------------------------------------------------ + /// Read the section data from the object file that the section + /// resides in. + /// + /// @param[in] dst + /// Where to place the data + /// + /// @param[in] dst_len + /// How many bytes of section data to read + /// + /// @param[in] offset + /// The offset in bytes within this section's data at which to + /// start copying data from. + /// + /// @return + /// The number of bytes read from the section, or zero if the + /// section has no data or \a offset is not a valid offset + /// in this section. + //------------------------------------------------------------------ + lldb::offset_t + GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset = 0); + + //------------------------------------------------------------------ + /// Get the shared reference to the section data from the object + /// file that the section resides in. No copies of the data will be + /// make unless the object file has been read from memory. If the + /// object file is on disk, it will shared the mmap data for the + /// entire object file. + /// + /// @param[in] data + /// Where to place the data, address byte size, and byte order + /// + /// @return + /// The number of bytes read from the section, or zero if the + /// section has no data or \a offset is not a valid offset + /// in this section. + //------------------------------------------------------------------ + lldb::offset_t + GetSectionData (DataExtractor& data) const; + uint32_t GetLog2Align() { return m_log2align; diff --git a/include/lldb/Core/SourceManager.h b/include/lldb/Core/SourceManager.h index 0f65be1bee4b..5504bafd6b7e 100644 --- a/include/lldb/Core/SourceManager.h +++ b/include/lldb/Core/SourceManager.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include // Other libraries and framework includes @@ -26,15 +27,17 @@ class SourceManager { public: #ifndef SWIG - class File { - friend bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs); + friend bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs); + public: - File (const FileSpec &file_spec, Target *target); ~File(); + void + UpdateIfNeeded (); + size_t DisplaySourceLines (uint32_t line, uint32_t context_before, @@ -80,7 +83,6 @@ public: GetNumLines (); protected: - bool CalculateLineOffsets (uint32_t line = UINT32_MAX); @@ -92,20 +94,18 @@ public: typedef std::vector LineOffsets; LineOffsets m_offsets; }; - #endif // SWIG typedef std::shared_ptr FileSP; #ifndef SWIG - // The SourceFileCache class separates the source manager from the cache of source files, so the // cache can be stored in the Debugger, but the source managers can be per target. class SourceFileCache { public: - SourceFileCache () {} - ~SourceFileCache() {} + SourceFileCache() = default; + ~SourceFileCache() = default; void AddSourceFile (const FileSP &file_sp); FileSP FindSourceFile (const FileSpec &file_spec) const; @@ -114,8 +114,7 @@ public: typedef std::map FileCache; FileCache m_file_cache; }; -#endif - +#endif // SWIG //------------------------------------------------------------------ // Constructors and Destructors @@ -127,7 +126,6 @@ public: ~SourceManager(); - FileSP GetLastFile () { @@ -135,28 +133,28 @@ public: } size_t - DisplaySourceLinesWithLineNumbers (const FileSpec &file, - uint32_t line, - uint32_t context_before, - uint32_t context_after, - const char* current_line_cstr, - Stream *s, - const SymbolContextList *bp_locs = NULL); + DisplaySourceLinesWithLineNumbers(const FileSpec &file, + uint32_t line, + uint32_t context_before, + uint32_t context_after, + const char* current_line_cstr, + Stream *s, + const SymbolContextList *bp_locs = nullptr); // This variant uses the last file we visited. size_t - DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line, - uint32_t count, - uint32_t curr_line, - const char* current_line_cstr, - Stream *s, - const SymbolContextList *bp_locs = NULL); + DisplaySourceLinesWithLineNumbersUsingLastFile(uint32_t start_line, + uint32_t count, + uint32_t curr_line, + const char* current_line_cstr, + Stream *s, + const SymbolContextList *bp_locs = nullptr); size_t - DisplayMoreWithLineNumbers (Stream *s, - uint32_t count, - bool reverse, - const SymbolContextList *bp_locs = NULL); + DisplayMoreWithLineNumbers(Stream *s, + uint32_t count, + bool reverse, + const SymbolContextList *bp_locs = nullptr); bool SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line); @@ -167,7 +165,7 @@ public: bool DefaultFileAndLineSet () { - return (m_last_file_sp.get() != NULL); + return (m_last_file_sp.get() != nullptr); } void @@ -181,10 +179,6 @@ public: GetFile (const FileSpec &file_spec); protected: - - //------------------------------------------------------------------ - // Classes that inherit from SourceManager can see and modify these - //------------------------------------------------------------------ FileSP m_last_file_sp; uint32_t m_last_line; uint32_t m_last_count; @@ -193,13 +187,11 @@ protected: lldb::DebuggerWP m_debugger_wp; private: - //------------------------------------------------------------------ - // For SourceManager only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (SourceManager); }; bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs); + } // namespace lldb_private -#endif // liblldb_SourceManager_h_ +#endif // liblldb_SourceManager_h_ diff --git a/include/lldb/Core/Stream.h b/include/lldb/Core/Stream.h index 11780aa6ff0f..f784069894ec 100644 --- a/include/lldb/Core/Stream.h +++ b/include/lldb/Core/Stream.h @@ -9,11 +9,15 @@ #ifndef liblldb_Stream_h_ #define liblldb_Stream_h_ -#if defined(__cplusplus) +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Flags.h" -#include namespace lldb_private { @@ -221,7 +225,7 @@ public: /// in one statement. //------------------------------------------------------------------ Stream& - operator<< (void *p); + operator<< (const void *p); //------------------------------------------------------------------ /// Output a character \a ch to the stream \a s. @@ -353,13 +357,13 @@ public: /// Size in bytes of the address, used for formatting. /// /// @param[in] prefix - /// A prefix C string. If NULL, no prefix will be output. + /// A prefix C string. If nullptr, no prefix will be output. /// /// @param[in] suffix - /// A suffix C string. If NULL, no suffix will be output. + /// A suffix C string. If nullptr, no suffix will be output. //------------------------------------------------------------------ void - Address (uint64_t addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL); + Address(uint64_t addr, uint32_t addr_size, const char *prefix = nullptr, const char *suffix = nullptr); //------------------------------------------------------------------ /// Output an address range to this stream. @@ -377,13 +381,13 @@ public: /// Size in bytes of the address, used for formatting. /// /// @param[in] prefix - /// A prefix C string. If NULL, no prefix will be output. + /// A prefix C string. If nullptr, no prefix will be output. /// /// @param[in] suffix - /// A suffix C string. If NULL, no suffix will be output. + /// A suffix C string. If nullptr, no suffix will be output. //------------------------------------------------------------------ void - AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL); + AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix = nullptr, const char *suffix = nullptr); //------------------------------------------------------------------ /// Output a C string to the stream. @@ -475,11 +479,11 @@ public: /// print an optional string following the indentation spaces. /// /// @param[in] s - /// A C string to print following the indentation. If NULL, just + /// A C string to print following the indentation. If nullptr, just /// output the indentation characters. //------------------------------------------------------------------ size_t - Indent(const char *s = NULL); + Indent(const char *s = nullptr); //------------------------------------------------------------------ /// Decrement the current indentation level. @@ -607,6 +611,4 @@ protected: } // namespace lldb_private -#endif // #if defined(__cplusplus) #endif // liblldb_Stream_h_ - diff --git a/include/lldb/Core/StreamAsynchronousIO.h b/include/lldb/Core/StreamAsynchronousIO.h index d3b054463fa7..b069cfd496e1 100644 --- a/include/lldb/Core/StreamAsynchronousIO.h +++ b/include/lldb/Core/StreamAsynchronousIO.h @@ -22,14 +22,13 @@ class StreamAsynchronousIO : public: StreamAsynchronousIO (Debugger &debugger, bool for_stdout); - virtual ~StreamAsynchronousIO (); + ~StreamAsynchronousIO () override; - virtual void - Flush (); - - virtual size_t - Write (const void *src, size_t src_len); + void + Flush () override; + size_t + Write (const void *src, size_t src_len) override; private: Debugger &m_debugger; @@ -38,4 +37,5 @@ private: }; } // namespace lldb_private -#endif // #ifndef liblldb_StreamAsynchronousIO_h + +#endif // liblldb_StreamAsynchronousIO_h diff --git a/include/lldb/Core/StreamCallback.h b/include/lldb/Core/StreamCallback.h index b5fb91c6ce07..e5a9da7512bb 100644 --- a/include/lldb/Core/StreamCallback.h +++ b/include/lldb/Core/StreamCallback.h @@ -24,14 +24,13 @@ class StreamCallback : public: StreamCallback (lldb::LogOutputCallback callback, void *baton); - virtual ~StreamCallback (); + ~StreamCallback () override; - virtual void - Flush (); - - virtual size_t - Write (const void *src, size_t src_len); + void + Flush () override; + size_t + Write (const void *src, size_t src_len) override; private: typedef std::map collection; @@ -44,4 +43,5 @@ private: }; } // namespace lldb_private -#endif // #ifndef liblldb_StreamCallback_h + +#endif // liblldb_StreamCallback_h diff --git a/include/lldb/Core/StreamFile.h b/include/lldb/Core/StreamFile.h index 55bb361780a5..781f0a599493 100644 --- a/include/lldb/Core/StreamFile.h +++ b/include/lldb/Core/StreamFile.h @@ -43,8 +43,7 @@ public: StreamFile (FILE *fh, bool transfer_ownership); - virtual - ~StreamFile(); + ~StreamFile() override; File & GetFile () @@ -58,11 +57,11 @@ public: return m_file; } - virtual void - Flush (); + void + Flush () override; - virtual size_t - Write (const void *s, size_t length); + size_t + Write (const void *s, size_t length) override; protected: //------------------------------------------------------------------ @@ -76,4 +75,4 @@ private: } // namespace lldb_private -#endif // liblldb_StreamFile_h_ +#endif // liblldb_StreamFile_h_ diff --git a/include/lldb/Core/StreamGDBRemote.h b/include/lldb/Core/StreamGDBRemote.h index 3fdb6f6e7012..834f412d0a03 100644 --- a/include/lldb/Core/StreamGDBRemote.h +++ b/include/lldb/Core/StreamGDBRemote.h @@ -29,8 +29,7 @@ namespace lldb_private { uint32_t addr_size, lldb::ByteOrder byte_order); - virtual - ~StreamGDBRemote (); + ~StreamGDBRemote() override; //------------------------------------------------------------------ /// Output a block of data to the stream performing GDB-remote escaping. @@ -51,4 +50,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // liblldb_StreamGDBRemote_h_ +#endif // liblldb_StreamGDBRemote_h_ diff --git a/include/lldb/Core/StreamString.h b/include/lldb/Core/StreamString.h index 1aa46dd80a68..5b6bde7a13c2 100644 --- a/include/lldb/Core/StreamString.h +++ b/include/lldb/Core/StreamString.h @@ -25,14 +25,13 @@ public: uint32_t addr_size, lldb::ByteOrder byte_order); - virtual - ~StreamString (); + ~StreamString () override; - virtual void - Flush (); + void + Flush () override; - virtual size_t - Write (const void *s, size_t length); + size_t + Write (const void *s, size_t length) override; void Clear(); @@ -60,8 +59,8 @@ public: protected: std::string m_packet; - }; } // namespace lldb_private -#endif // #ifndef liblldb_StreamString_h_ + +#endif // liblldb_StreamString_h_ diff --git a/include/lldb/Core/StreamTee.h b/include/lldb/Core/StreamTee.h index e2a29a374553..7ab619b3bb79 100644 --- a/include/lldb/Core/StreamTee.h +++ b/include/lldb/Core/StreamTee.h @@ -59,8 +59,7 @@ public: m_streams = rhs.m_streams; } - virtual - ~StreamTee () + ~StreamTee () override { } @@ -76,8 +75,8 @@ public: return *this; } - virtual void - Flush () + void + Flush () override { Mutex::Locker locker (m_streams_mutex); collection::iterator pos, end; @@ -93,8 +92,8 @@ public: } } - virtual size_t - Write (const void *s, size_t length) + size_t + Write (const void *s, size_t length) override { Mutex::Locker locker (m_streams_mutex); if (m_streams.empty()) @@ -164,7 +163,6 @@ public: m_streams[idx] = stream_sp; } - protected: typedef std::vector collection; mutable Mutex m_streams_mutex; @@ -172,4 +170,5 @@ protected: }; } // namespace lldb_private -#endif // #ifndef liblldb_StreamTee_h_ + +#endif // liblldb_StreamTee_h_ diff --git a/include/lldb/Core/StringList.h b/include/lldb/Core/StringList.h index c69ed872c30d..3e341b994075 100644 --- a/include/lldb/Core/StringList.h +++ b/include/lldb/Core/StringList.h @@ -10,18 +10,24 @@ #ifndef liblldb_StringList_h_ #define liblldb_StringList_h_ +// C Includes #include -#include "lldb/Core/STLUtils.h" -#include "lldb/lldb-forward.h" +// C++ Includes +#include + +// Other libraries and framework includes #include "llvm/ADT/StringRef.h" +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/Core/STLUtils.h" + namespace lldb_private { class StringList { public: - StringList (); StringList (const char *str); @@ -120,7 +126,7 @@ public: SplitIntoLines (const char *lines, size_t len); std::string - CopyList(const char* item_preamble = NULL, + CopyList(const char* item_preamble = nullptr, const char* items_sep = "\n") const; StringList& @@ -142,7 +148,6 @@ public: size_t &exact_matches_idx) const; private: - STLStringArray m_strings; }; diff --git a/include/lldb/Core/StructuredData.h b/include/lldb/Core/StructuredData.h index 7da29e48299d..52f34521ef0e 100644 --- a/include/lldb/Core/StructuredData.h +++ b/include/lldb/Core/StructuredData.h @@ -12,16 +12,16 @@ // C Includes // C++ Includes - #include #include +#include #include #include #include +// Other libraries and framework includes #include "llvm/ADT/StringRef.h" -// Other libraries and framework includes // Project includes #include "lldb/lldb-defines.h" #include "lldb/Core/ConstString.h" @@ -47,7 +47,6 @@ namespace lldb_private { class StructuredData { public: - class Object; class Array; class Integer; @@ -89,9 +88,7 @@ public: { } - virtual ~Object () - { - } + virtual ~Object() = default; virtual bool IsValid() const @@ -120,80 +117,62 @@ public: Array * GetAsArray () { - if (m_type == Type::eTypeArray) - return (Array *)this; - return NULL; + return ((m_type == Type::eTypeArray) ? static_cast(this) : nullptr); } Dictionary * GetAsDictionary () { - if (m_type == Type::eTypeDictionary) - return (Dictionary *)this; - return NULL; + return ((m_type == Type::eTypeDictionary) ? static_cast(this) : nullptr); } Integer * GetAsInteger () { - if (m_type == Type::eTypeInteger) - return (Integer *)this; - return NULL; + return ((m_type == Type::eTypeInteger) ? static_cast(this) : nullptr); } uint64_t GetIntegerValue (uint64_t fail_value = 0) { Integer *integer = GetAsInteger (); - if (integer) - return integer->GetValue(); - return fail_value; + return ((integer != nullptr) ? integer->GetValue() : fail_value); } Float * GetAsFloat () { - if (m_type == Type::eTypeFloat) - return (Float *)this; - return NULL; + return ((m_type == Type::eTypeFloat) ? static_cast(this) : nullptr); } double GetFloatValue (double fail_value = 0.0) { Float *f = GetAsFloat (); - if (f) - return f->GetValue(); - return fail_value; + return ((f != nullptr) ? f->GetValue() : fail_value); } Boolean * GetAsBoolean () { - if (m_type == Type::eTypeBoolean) - return (Boolean *)this; - return NULL; + return ((m_type == Type::eTypeBoolean) ? static_cast(this) : nullptr); } bool GetBooleanValue (bool fail_value = false) { Boolean *b = GetAsBoolean (); - if (b) - return b->GetValue(); - return fail_value; + return ((b != nullptr) ? b->GetValue() : fail_value); } String * GetAsString () { - if (m_type == Type::eTypeString) - return (String *)this; - return NULL; + return ((m_type == Type::eTypeString) ? static_cast(this) : nullptr); } std::string - GetStringValue(const char *fail_value = NULL) + GetStringValue(const char *fail_value = nullptr) { String *s = GetAsString (); if (s) @@ -208,9 +187,7 @@ public: Generic * GetAsGeneric() { - if (m_type == Type::eTypeGeneric) - return (Generic *)this; - return NULL; + return ((m_type == Type::eTypeGeneric) ? static_cast(this) : nullptr); } ObjectSP @@ -233,10 +210,7 @@ public: { } - virtual - ~Array() - { - } + ~Array() override = default; bool ForEach (std::function const &foreach_callback) const @@ -249,7 +223,6 @@ public: return true; } - size_t GetSize() const { @@ -277,11 +250,14 @@ public: bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const { - ObjectSP value = GetItemAtIndex(idx); - if (auto int_value = value->GetAsInteger()) + ObjectSP value_sp = GetItemAtIndex(idx); + if (value_sp.get()) { - result = static_cast(int_value->GetValue()); - return true; + if (auto int_value = value_sp->GetAsInteger()) + { + result = static_cast(int_value->GetValue()); + return true; + } } return false; } @@ -299,11 +275,14 @@ public: bool GetItemAtIndexAsString(size_t idx, std::string &result) const { - ObjectSP value = GetItemAtIndex(idx); - if (auto string_value = value->GetAsString()) + ObjectSP value_sp = GetItemAtIndex(idx); + if (value_sp.get()) { - result = string_value->GetValue(); - return true; + if (auto string_value = value_sp->GetAsString()) + { + result = string_value->GetValue(); + return true; + } } return false; } @@ -320,13 +299,13 @@ public: bool GetItemAtIndexAsString(size_t idx, ConstString &result) const { - ObjectSP value = GetItemAtIndex(idx); - if (!value) - return false; - if (auto string_value = value->GetAsString()) - { - result = ConstString(string_value->GetValue()); - return true; + ObjectSP value_sp = GetItemAtIndex(idx); + if (value_sp.get()) { + if (auto string_value = value_sp->GetAsString()) + { + result = ConstString(string_value->GetValue()); + return true; + } } return false; } @@ -343,17 +322,27 @@ public: bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const { - ObjectSP value = GetItemAtIndex(idx); - result = value->GetAsDictionary(); - return (result != nullptr); + result = nullptr; + ObjectSP value_sp = GetItemAtIndex(idx); + if (value_sp.get()) + { + result = value_sp->GetAsDictionary(); + return (result != nullptr); + } + return false; } bool GetItemAtIndexAsArray(size_t idx, Array *&result) const { - ObjectSP value = GetItemAtIndex(idx); - result = value->GetAsArray(); - return (result != nullptr); + result = nullptr; + ObjectSP value_sp = GetItemAtIndex(idx); + if (value_sp.get()) + { + result = value_sp->GetAsArray(); + return (result != nullptr); + } + return false; } void @@ -375,8 +364,7 @@ public: collection m_items; }; - - class Integer : public Object + class Integer : public Object { public: Integer (uint64_t i = 0) : @@ -385,9 +373,7 @@ public: { } - virtual ~Integer() - { - } + ~Integer() override = default; void SetValue (uint64_t value) @@ -407,7 +393,7 @@ public: uint64_t m_value; }; - class Float : public Object + class Float : public Object { public: Float (double d = 0.0) : @@ -416,9 +402,7 @@ public: { } - virtual ~Float() - { - } + ~Float() override = default; void SetValue (double value) @@ -438,7 +422,7 @@ public: double m_value; }; - class Boolean : public Object + class Boolean : public Object { public: Boolean (bool b = false) : @@ -447,9 +431,7 @@ public: { } - virtual ~Boolean() - { - } + ~Boolean() override = default; void SetValue (bool value) @@ -469,12 +451,10 @@ public: bool m_value; }; - - - class String : public Object + class String : public Object { public: - String (const char *cstr = NULL) : + String(const char *cstr = nullptr) : Object (Type::eTypeString), m_value () { @@ -522,9 +502,7 @@ public: { } - virtual ~Dictionary() - { - } + ~Dictionary() override = default; size_t GetSize() const @@ -580,13 +558,13 @@ public: bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const { - ObjectSP value = GetValueForKey(key); - if (!value) - return false; - if (auto int_value = value->GetAsInteger()) - { - result = static_cast(int_value->GetValue()); - return true; + ObjectSP value_sp = GetValueForKey(key); + if (value_sp) { + if (auto int_value = value_sp->GetAsInteger()) + { + result = static_cast(int_value->GetValue()); + return true; + } } return false; } @@ -604,13 +582,14 @@ public: bool GetValueForKeyAsString(llvm::StringRef key, std::string &result) const { - ObjectSP value = GetValueForKey(key); - if (!value) - return false; - if (auto string_value = value->GetAsString()) + ObjectSP value_sp = GetValueForKey(key); + if (value_sp.get()) { - result = string_value->GetValue(); - return true; + if (auto string_value = value_sp->GetAsString()) + { + result = string_value->GetValue(); + return true; + } } return false; } @@ -632,13 +611,14 @@ public: bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result) const { - ObjectSP value = GetValueForKey(key); - if (!value) - return false; - if (auto string_value = value->GetAsString()) + ObjectSP value_sp = GetValueForKey(key); + if (value_sp.get()) { - result = ConstString(string_value->GetValue()); - return true; + if (auto string_value = value_sp->GetAsString()) + { + result = ConstString(string_value->GetValue()); + return true; + } } return false; } @@ -656,22 +636,26 @@ public: GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const { result = nullptr; - ObjectSP value = GetValueForKey(key); - if (!value) - return false; - result = value->GetAsDictionary(); - return true; + ObjectSP value_sp = GetValueForKey(key); + if (value_sp.get()) + { + result = value_sp->GetAsDictionary(); + return (result != nullptr); + } + return false; } bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const { result = nullptr; - ObjectSP value = GetValueForKey(key); - if (!value) - return false; - result = value->GetAsArray(); - return true; + ObjectSP value_sp = GetValueForKey(key); + if (value_sp.get()) + { + result = value_sp->GetAsArray(); + return (result != nullptr); + } + return false; } bool @@ -683,10 +667,10 @@ public: } void - AddItem (llvm::StringRef key, ObjectSP value) + AddItem (llvm::StringRef key, ObjectSP value_sp) { ConstString key_cs(key); - m_dict[key_cs] = value; + m_dict[key_cs] = value_sp; } void @@ -728,9 +712,7 @@ public: { } - virtual ~Null() - { - } + ~Null() override = default; bool IsValid() const override @@ -739,13 +721,11 @@ public: } void Dump(Stream &s) const override; - - protected: }; class Generic : public Object { - public: + public: explicit Generic(void *object = nullptr) : Object (Type::eTypeGeneric), m_object (object) @@ -772,16 +752,14 @@ public: void Dump(Stream &s) const override; - private: + private: void *m_object; }; static ObjectSP ParseJSON (std::string json_text); - -}; // class StructuredData - +}; } // namespace lldb_private -#endif // liblldb_StructuredData_h_ +#endif // liblldb_StructuredData_h_ diff --git a/include/lldb/Core/ThreadSafeDenseMap.h b/include/lldb/Core/ThreadSafeDenseMap.h index f5a7ccfb2ffa..6b2b59b7617c 100644 --- a/include/lldb/Core/ThreadSafeDenseMap.h +++ b/include/lldb/Core/ThreadSafeDenseMap.h @@ -54,7 +54,27 @@ public: Mutex::Locker locker(m_mutex); return m_map.lookup(k); } - + + bool + Lookup (_KeyType k, + _ValueType& v) + { + Mutex::Locker locker(m_mutex); + auto iter = m_map.find(k), + end = m_map.end(); + if (iter == end) + return false; + v = iter->second; + return true; + } + + void + Clear () + { + Mutex::Locker locker(m_mutex); + m_map.clear(); + } + protected: LLVMMapType m_map; Mutex m_mutex; diff --git a/include/lldb/Core/ThreadSafeDenseSet.h b/include/lldb/Core/ThreadSafeDenseSet.h index 19c67b65e8c1..e019c70ed5e5 100644 --- a/include/lldb/Core/ThreadSafeDenseSet.h +++ b/include/lldb/Core/ThreadSafeDenseSet.h @@ -55,6 +55,13 @@ namespace lldb_private { return (m_set.count(e) > 0); } + void + Clear () + { + Mutex::Locker locker(m_mutex); + m_set.clear(); + } + protected: LLVMSetType m_set; Mutex m_mutex; diff --git a/include/lldb/Core/Timer.h b/include/lldb/Core/Timer.h index e354d91be442..ffaeba6fce9b 100644 --- a/include/lldb/Core/Timer.h +++ b/include/lldb/Core/Timer.h @@ -9,11 +9,17 @@ #ifndef liblldb_Timer_h_ #define liblldb_Timer_h_ -#if defined(__cplusplus) +// C Includes #include #include -#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/TimeValue.h" @@ -34,19 +40,19 @@ namespace lldb_private { class Timer { public: - static void - Initialize (); - //-------------------------------------------------------------- /// Default constructor. //-------------------------------------------------------------- Timer(const char *category, const char *format, ...) __attribute__ ((format (printf, 3, 4))); //-------------------------------------------------------------- - /// Desstructor + /// Destructor //-------------------------------------------------------------- ~Timer(); + static void + Initialize (); + void Dump (); @@ -63,7 +69,6 @@ public: ResetCategoryTimes (); protected: - void ChildStarted (const TimeValue& time); @@ -76,17 +81,17 @@ protected: uint64_t GetTimerElapsedNanoSeconds(); - //-------------------------------------------------------------- - /// Member variables - //-------------------------------------------------------------- const char *m_category; TimeValue m_total_start; TimeValue m_timer_start; uint64_t m_total_ticks; // Total running time for this timer including when other timers below this are running uint64_t m_timer_ticks; // Ticks for this timer that do not include when other timers below this one are running - static uint32_t g_depth; - static uint32_t g_display_depth; - static FILE * g_file; + + static std::atomic g_quiet; + static std::atomic g_display_depth; + static std::mutex g_file_mutex; + static FILE* g_file; + private: Timer(); DISALLOW_COPY_AND_ASSIGN (Timer); @@ -99,10 +104,8 @@ public: m_start (TimeValue::Now()) { } - - ~IntervalTimer() - { - } + + ~IntervalTimer() = default; uint64_t GetElapsedNanoSeconds() const @@ -121,7 +124,7 @@ public: { TimeValue now (TimeValue::Now()); const uint64_t elapsed_nsec = now - m_start; - const char *unit = NULL; + const char *unit = nullptr; float elapsed_value; if (elapsed_nsec < 1000) { @@ -150,11 +153,11 @@ public: va_end (args); return result; } + protected: TimeValue m_start; }; } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // #ifndef liblldb_Timer_h_ +#endif // liblldb_Timer_h_ diff --git a/include/lldb/Core/UUID.h b/include/lldb/Core/UUID.h index 3bb14421b1e9..88426cfb6c75 100644 --- a/include/lldb/Core/UUID.h +++ b/include/lldb/Core/UUID.h @@ -16,7 +16,6 @@ // Other libraries and framework includes // Project includes - #include "lldb/lldb-private.h" namespace lldb_private { @@ -58,7 +57,7 @@ public: SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16); std::string - GetAsString (const char *separator = NULL) const; + GetAsString(const char *separator = nullptr) const; size_t SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16); @@ -80,7 +79,7 @@ public: /// decoded UUID. /// /// @param[out] end - /// If \a end is not NULL, it will be filled in with the a + /// If \a end is not nullptr, it will be filled in with the a /// pointer to the character after the last successfully decoded /// byte. /// diff --git a/include/lldb/Core/UniqueCStringMap.h b/include/lldb/Core/UniqueCStringMap.h index 972c0d53ea99..1e50f747f2a8 100644 --- a/include/lldb/Core/UniqueCStringMap.h +++ b/include/lldb/Core/UniqueCStringMap.h @@ -9,18 +9,18 @@ #ifndef liblldb_UniqueCStringMap_h_ #define liblldb_UniqueCStringMap_h_ -#if defined(__cplusplus) -#include +// C Includes +// C++ Includes #include #include +// Other libraries and framework includes +// Project includes #include "lldb/Core/RegularExpression.h" namespace lldb_private { - - //---------------------------------------------------------------------- // Templatized uniqued string map. // @@ -37,7 +37,7 @@ public: struct Entry { Entry () : - cstring(NULL), + cstring(nullptr), value() { } @@ -146,9 +146,7 @@ public: const char * GetCStringAtIndex (uint32_t idx) const { - if (idx < m_map.size()) - return m_map[idx].cstring; - return NULL; + return ((idx < m_map.size()) ? m_map[idx].cstring : nullptr); } //------------------------------------------------------------------ @@ -172,8 +170,9 @@ public: } return fail_value; } + //------------------------------------------------------------------ - // Get a pointer to the first entry that matches "name". NULL will + // Get a pointer to the first entry that matches "name". nullptr will // be returned if there is no entry that matches "name". // // The caller is responsible for ensuring that the collection does @@ -191,12 +190,12 @@ public: if (pos_cstr == unique_cstr) return &(*pos); } - return NULL; + return nullptr; } //------------------------------------------------------------------ // Get a pointer to the next entry that matches "name" from a - // previously returned Entry pointer. NULL will be returned if there + // previously returned Entry pointer. nullptr will be returned if there // is no subsequent entry that matches "name". // // The caller is responsible for ensuring that the collection does @@ -216,7 +215,7 @@ public: return next_entry; } } - return NULL; + return nullptr; } size_t @@ -261,7 +260,6 @@ public: return m_map.size(); } - //------------------------------------------------------------------ // Returns true if this map is empty. //------------------------------------------------------------------ @@ -346,6 +344,7 @@ public: } return num_removed; } + protected: typedef std::vector collection; typedef typename collection::iterator iterator; @@ -353,9 +352,6 @@ protected: collection m_map; }; - - } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_UniqueCStringMap_h_ +#endif // liblldb_UniqueCStringMap_h_ diff --git a/include/lldb/Core/Value.h b/include/lldb/Core/Value.h index 957cedeb0dcc..a6d934afd294 100644 --- a/include/lldb/Core/Value.h +++ b/include/lldb/Core/Value.h @@ -12,23 +12,21 @@ // C Includes // C++ Includes -#include #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Scalar.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" namespace lldb_private { class Value { public: - // Values Less than zero are an error, greater than or equal to zero // returns what the Scalar result is. enum ValueType @@ -101,6 +99,7 @@ public: // Casts a vector, if valid, to an unsigned int of matching or largest supported size. // Truncates to the beginning of the vector if required. // Returns a default constructed Scalar if the Vector data is internally inconsistent. + llvm::APInt rhs = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)bytes)->x); Scalar GetAsScalar() const { @@ -111,11 +110,7 @@ public: else if (length == 2) scalar = *(const uint16_t *)bytes; else if (length == 4) scalar = *(const uint32_t *)bytes; else if (length == 8) scalar = *(const uint64_t *)bytes; -#if defined (ENABLE_128_BIT_SUPPORT) - else if (length >= 16) scalar = *(const __uint128_t *)bytes; -#else - else if (length >= 16) scalar = *(const uint64_t *)bytes; -#endif + else if (length >= 16) scalar = rhs; } return scalar; } @@ -136,11 +131,11 @@ public: Value & operator=(const Value &rhs); - const ClangASTType & - GetClangType(); + const CompilerType & + GetCompilerType(); void - SetClangType (const ClangASTType &clang_type); + SetCompilerType (const CompilerType &compiler_type); ValueType GetValueType() const; @@ -163,7 +158,7 @@ public: void ClearContext () { - m_context = NULL; + m_context = nullptr; m_context_type = eContextTypeInvalid; } @@ -269,13 +264,13 @@ public: GetValueDefaultFormat (); uint64_t - GetValueByteSize (Error *error_ptr); + GetValueByteSize (Error *error_ptr, ExecutionContext *exe_ctx); Error - GetValueAsData (ExecutionContext *exe_ctx, - DataExtractor &data, - uint32_t data_offset, - Module *module); // Can be NULL + GetValueAsData(ExecutionContext *exe_ctx, + DataExtractor &data, + uint32_t data_offset, + Module *module); // Can be nullptr static const char * GetValueTypeAsCString (ValueType context_type); @@ -292,7 +287,7 @@ public: protected: Scalar m_value; Vector m_vector; - ClangASTType m_clang_type; + CompilerType m_compiler_type; void * m_context; ValueType m_value_type; ContextType m_context_type; @@ -309,9 +304,7 @@ public: ValueList (const ValueList &rhs); - ~ValueList () - { - } + ~ValueList() = default; const ValueList & operator= (const ValueList &rhs); @@ -322,8 +315,6 @@ public: Value *GetValueAtIndex(size_t idx); void Clear(); -protected: - private: typedef std::vector collection; @@ -332,4 +323,4 @@ private: } // namespace lldb_private -#endif // liblldb_Value_h_ +#endif // liblldb_Value_h_ diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h index cdc507093b28..c066cc7d3661 100644 --- a/include/lldb/Core/ValueObject.h +++ b/include/lldb/Core/ValueObject.h @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include +#include #include #include @@ -27,7 +29,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/UserID.h" #include "lldb/Core/Value.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Process.h" @@ -69,7 +71,6 @@ namespace lldb_private { class ValueObject : public UserID { public: - enum GetExpressionPathFormat { eGetExpressionPathFormatDereferencePointers = 1, @@ -221,13 +222,11 @@ public: return g_default_options; } - }; class EvaluationPoint { public: - EvaluationPoint (); EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected = false); @@ -326,6 +325,8 @@ public: bool m_needs_update; }; + virtual ~ValueObject(); + const EvaluationPoint & GetUpdatePoint () const { @@ -371,10 +372,8 @@ public: void SetNeedsUpdate (); - virtual ~ValueObject(); - - ClangASTType - GetClangType (); + CompilerType + GetCompilerType (); // this vends a TypeImpl that is useful at the SB API layer virtual TypeImpl @@ -408,7 +407,7 @@ public: GetObjectRuntimeLanguage(); virtual uint32_t - GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL); + GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr); virtual bool IsPointerType (); @@ -425,8 +424,11 @@ public: virtual bool IsPossibleDynamicType (); - virtual bool - IsObjCNil (); + bool + IsNilReference (); + + bool + IsUninitializedReference (); virtual bool IsBaseClass () @@ -454,20 +456,20 @@ public: lldb::ValueObjectSP GetValueForExpressionPath(const char* expression, - const char** first_unparsed = NULL, - ExpressionPathScanEndReason* reason_to_stop = NULL, - ExpressionPathEndResultType* final_value_type = NULL, + const char** first_unparsed = nullptr, + ExpressionPathScanEndReason* reason_to_stop = nullptr, + ExpressionPathEndResultType* final_value_type = nullptr, const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), - ExpressionPathAftermath* final_task_on_target = NULL); + ExpressionPathAftermath* final_task_on_target = nullptr); int GetValuesForExpressionPath(const char* expression, lldb::ValueObjectListSP& list, - const char** first_unparsed = NULL, - ExpressionPathScanEndReason* reason_to_stop = NULL, - ExpressionPathEndResultType* final_value_type = NULL, + const char** first_unparsed = nullptr, + ExpressionPathScanEndReason* reason_to_stop = nullptr, + ExpressionPathEndResultType* final_value_type = nullptr, const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), - ExpressionPathAftermath* final_task_on_target = NULL); + ExpressionPathAftermath* final_task_on_target = nullptr); virtual bool IsInScope () @@ -517,10 +519,10 @@ public: std::string& destination); virtual uint64_t - GetValueAsUnsigned (uint64_t fail_value, bool *success = NULL); + GetValueAsUnsigned(uint64_t fail_value, bool *success = nullptr); virtual int64_t - GetValueAsSigned (int64_t fail_value, bool *success = NULL); + GetValueAsSigned(int64_t fail_value, bool *success = nullptr); virtual bool SetValueFromCString (const char *value_str, Error& error); @@ -556,37 +558,37 @@ public: // this will always create the children if necessary lldb::ValueObjectSP - GetChildAtIndexPath (const std::initializer_list &idxs, - size_t* index_of_error = NULL); + GetChildAtIndexPath(const std::initializer_list &idxs, + size_t* index_of_error = nullptr); lldb::ValueObjectSP - GetChildAtIndexPath (const std::vector &idxs, - size_t* index_of_error = NULL); + GetChildAtIndexPath(const std::vector &idxs, + size_t* index_of_error = nullptr); lldb::ValueObjectSP - GetChildAtIndexPath (const std::initializer_list< std::pair > &idxs, - size_t* index_of_error = NULL); + GetChildAtIndexPath(const std::initializer_list< std::pair > &idxs, + size_t* index_of_error = nullptr); lldb::ValueObjectSP - GetChildAtIndexPath (const std::vector< std::pair > &idxs, - size_t* index_of_error = NULL); + GetChildAtIndexPath(const std::vector< std::pair > &idxs, + size_t* index_of_error = nullptr); // this will always create the children if necessary lldb::ValueObjectSP - GetChildAtNamePath (const std::initializer_list &names, - ConstString* name_of_error = NULL); + GetChildAtNamePath(const std::initializer_list &names, + ConstString* name_of_error = nullptr); lldb::ValueObjectSP - GetChildAtNamePath (const std::vector &names, - ConstString* name_of_error = NULL); + GetChildAtNamePath(const std::vector &names, + ConstString* name_of_error = nullptr); lldb::ValueObjectSP - GetChildAtNamePath (const std::initializer_list< std::pair > &names, - ConstString* name_of_error = NULL); + GetChildAtNamePath(const std::initializer_list< std::pair > &names, + ConstString* name_of_error = nullptr); lldb::ValueObjectSP - GetChildAtNamePath (const std::vector< std::pair > &names, - ConstString* name_of_error = NULL); + GetChildAtNamePath(const std::vector< std::pair > &names, + ConstString* name_of_error = nullptr); virtual lldb::ValueObjectSP GetChildMemberWithName (const ConstString &name, bool can_create); @@ -595,7 +597,7 @@ public: GetIndexOfChildWithName (const ConstString &name); size_t - GetNumChildren (); + GetNumChildren (uint32_t max=UINT32_MAX); const Value & GetValue() const; @@ -606,15 +608,22 @@ public: virtual bool ResolveValue (Scalar &scalar); + // return 'false' whenever you set the error, otherwise + // callers may assume true means everything is OK - this will + // break breakpoint conditions among potentially a few others + virtual bool + IsLogicalTrue (Error& error); + virtual const char * GetLocationAsCString (); const char * - GetSummaryAsCString (); + GetSummaryAsCString (lldb::LanguageType lang = lldb::eLanguageTypeUnknown); bool GetSummaryAsCString (TypeSummaryImpl* summary_ptr, - std::string& destination); + std::string& destination, + lldb::LanguageType lang = lldb::eLanguageTypeUnknown); bool GetSummaryAsCString (std::string& destination, @@ -671,11 +680,11 @@ public: SetName (const ConstString &name); virtual lldb::addr_t - GetAddressOf (bool scalar_is_load_address = true, - AddressType *address_type = NULL); + GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr); lldb::addr_t - GetPointerValue (AddressType *address_type = NULL); + GetPointerValue(AddressType *address_type = nullptr); lldb::ValueObjectSP GetSyntheticChild (const ConstString &key) const; @@ -690,10 +699,10 @@ public: GetSyntheticExpressionPathChild(const char* expression, bool can_create); virtual lldb::ValueObjectSP - GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create); virtual lldb::ValueObjectSP - GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create); + GetSyntheticBase (uint32_t offset, const CompilerType& type, bool can_create); virtual lldb::ValueObjectSP GetDynamicValue (lldb::DynamicValueType valueType); @@ -746,11 +755,11 @@ public: GetCPPVTableAddress(AddressType &address_type); virtual lldb::ValueObjectSP - Cast (const ClangASTType &clang_ast_type); + Cast (const CompilerType &compiler_type); virtual lldb::ValueObjectSP CastPointerType (const char *name, - ClangASTType &ast_type); + CompilerType &ast_type); virtual lldb::ValueObjectSP CastPointerType (const char *name, @@ -809,13 +818,13 @@ public: CreateValueObjectFromAddress (const char* name, uint64_t address, const ExecutionContext& exe_ctx, - ClangASTType type); + CompilerType type); static lldb::ValueObjectSP CreateValueObjectFromData (const char* name, const DataExtractor& data, const ExecutionContext& exe_ctx, - ClangASTType type); + CompilerType type); void LogValueObject (Log *log); @@ -834,7 +843,7 @@ public: bool IsCStringContainer (bool check_pointer = false); - size_t + std::pair ReadPointedString (lldb::DataBufferSP& buffer_sp, Error& error, uint32_t max_length = 0, @@ -861,7 +870,7 @@ public: bool NeedsUpdating () { - const bool accept_invalid_exe_ctx = CanUpdateWithInvalidExecutionContext(); + const bool accept_invalid_exe_ctx = (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes); return m_update_point.NeedsUpdating(accept_invalid_exe_ctx); } @@ -881,8 +890,7 @@ public: ClearUserVisibleData(eClearUserVisibleDataItemsValue); m_format = format; } - - + virtual lldb::LanguageType GetPreferredDisplayLanguage (); @@ -999,8 +1007,20 @@ public: virtual bool MightHaveChildren(); + virtual lldb::VariableSP + GetVariable () + { + return nullptr; + } + virtual bool IsRuntimeSupportValue (); + + virtual uint64_t + GetLanguageFlags (); + + virtual void + SetLanguageFlags (uint64_t flags); protected: typedef ClusterManager ValueObjectManager; @@ -1018,21 +1038,15 @@ protected: HasChildAtIndex (size_t idx) { Mutex::Locker locker(m_mutex); - ChildrenIterator iter = m_children.find(idx); - ChildrenIterator end = m_children.end(); - return (iter != end); + return (m_children.find(idx) != m_children.end()); } ValueObject* GetChildAtIndex (size_t idx) { Mutex::Locker locker(m_mutex); - ChildrenIterator iter = m_children.find(idx); - ChildrenIterator end = m_children.end(); - if (iter == end) - return NULL; - else - return iter->second; + const auto iter = m_children.find(idx); + return ((iter == m_children.end()) ? nullptr : iter->second); } void @@ -1075,8 +1089,8 @@ protected: //------------------------------------------------------------------ // Classes that inherit from ValueObject can see and modify these //------------------------------------------------------------------ - ValueObject * m_parent; // The parent value object, or NULL if this has no parent - ValueObject * m_root; // The root of the hierarchy for this ValueObject (or NULL if never calculated) + ValueObject * m_parent; // The parent value object, or nullptr if this has no parent + ValueObject * m_root; // The root of the hierarchy for this ValueObject (or nullptr if never calculated) EvaluationPoint m_update_point; // Stores both the stop id and the full context at which this value was last // updated. When we are asked to update the value object, we check whether // the context & stop id are the same before updating. @@ -1093,7 +1107,7 @@ protected: llvm::Optional> m_validation_result; - ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose. + CompilerType m_override_type;// If the type of the value object should be overridden, the type to impose. ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created // without a parent.) The manager gets passed through all the generations of @@ -1125,6 +1139,8 @@ protected: lldb::LanguageType m_preferred_display_language; + uint64_t m_language_flags; + bool m_value_is_valid:1, m_value_did_change:1, m_children_count_valid:1, @@ -1139,7 +1155,7 @@ protected: friend class ValueObjectChild; friend class ClangExpressionDeclMap; // For GetValue - friend class ClangExpressionVariable; // For SetName + friend class ExpressionVariable; // For SetName friend class Target; // For SetName friend class ValueObjectConstResultImpl; friend class ValueObjectSynthetic; // For ClearUserVisibleData @@ -1172,10 +1188,10 @@ protected: virtual bool UpdateValue () = 0; - virtual bool + virtual LazyBool CanUpdateWithInvalidExecutionContext () { - return false; + return eLazyBoolCalculate; } virtual void @@ -1203,7 +1219,7 @@ protected: // Should only be called by ValueObject::GetNumChildren() virtual size_t - CalculateNumChildren() = 0; + CalculateNumChildren(uint32_t max=UINT32_MAX) = 0; void SetNumChildren (size_t num_children); @@ -1231,8 +1247,8 @@ protected: // Subclasses must implement the functions below. //------------------------------------------------------------------ - virtual ClangASTType - GetClangTypeImpl () = 0; + virtual CompilerType + GetCompilerTypeImpl () = 0; const char * GetLocationAsCStringImpl (const Value& value, @@ -1241,12 +1257,11 @@ protected: bool IsChecksumEmpty (); -private: - //------------------------------------------------------------------ - // For ValueObject only - //------------------------------------------------------------------ + void + SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType); - virtual ClangASTType +private: + virtual CompilerType MaybeCalculateCompleteType (); lldb::ValueObjectSP @@ -1270,12 +1285,10 @@ private: ExpressionPathEndResultType* final_value_type, const GetValueForExpressionPathOptions& options, ExpressionPathAftermath* final_task_on_target); - - - DISALLOW_COPY_AND_ASSIGN (ValueObject); + DISALLOW_COPY_AND_ASSIGN (ValueObject); }; } // namespace lldb_private -#endif // liblldb_ValueObject_h_ +#endif // liblldb_ValueObject_h_ diff --git a/include/lldb/Core/ValueObjectCast.h b/include/lldb/Core/ValueObjectCast.h index 1538d7a55639..8c7ffe5ec5e2 100644 --- a/include/lldb/Core/ValueObjectCast.h +++ b/include/lldb/Core/ValueObjectCast.h @@ -1,4 +1,4 @@ -//===-- ValueObjectDynamicValue.h -----------------------------------*- C++ -*-===// +//===-- ValueObjectDynamicValue.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -24,64 +24,54 @@ namespace lldb_private { class ValueObjectCast : public ValueObject { public: + ~ValueObjectCast() override; + static lldb::ValueObjectSP Create (ValueObject &parent, const ConstString &name, - const ClangASTType &cast_type); + const CompilerType &cast_type); - virtual - ~ValueObjectCast(); - - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual ValueObject * - GetParent() + ValueObject * + GetParent() override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } - virtual const ValueObject * - GetParent() const + const ValueObject * + GetParent() const override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } protected: - virtual bool - UpdateValue (); + ValueObjectCast(ValueObject &parent, + const ConstString &name, + const CompilerType &cast_type); + + bool + UpdateValue () override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl () override; - ClangASTType m_cast_type; + CompilerType m_cast_type; private: - ValueObjectCast (ValueObject &parent, - const ConstString &name, - const ClangASTType &cast_type); - - //------------------------------------------------------------------ - // For ValueObject only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (ValueObjectCast); }; } // namespace lldb_private -#endif // liblldb_ValueObjectCast_h_ +#endif // liblldb_ValueObjectCast_h_ diff --git a/include/lldb/Core/ValueObjectChild.h b/include/lldb/Core/ValueObjectChild.h index bf8707ea3b05..13e26c6ab0c1 100644 --- a/include/lldb/Core/ValueObjectChild.h +++ b/include/lldb/Core/ValueObjectChild.h @@ -16,6 +16,8 @@ // Project includes #include "lldb/Core/ValueObject.h" +#include "llvm/ADT/Optional.h" + namespace lldb_private { //---------------------------------------------------------------------- @@ -24,76 +26,76 @@ namespace lldb_private { class ValueObjectChild : public ValueObject { public: - virtual ~ValueObjectChild(); + ~ValueObjectChild() override; - virtual uint64_t - GetByteSize() + uint64_t + GetByteSize() override { return m_byte_size; } - virtual lldb::offset_t - GetByteOffset() + lldb::offset_t + GetByteOffset() override { return m_byte_offset; } - virtual uint32_t - GetBitfieldBitSize() + uint32_t + GetBitfieldBitSize() override { return m_bitfield_bit_size; } - virtual uint32_t - GetBitfieldBitOffset() + uint32_t + GetBitfieldBitOffset() override { return m_bitfield_bit_offset; } - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual bool - IsBaseClass () + bool + IsBaseClass() override { return m_is_base_class; } - virtual bool - IsDereferenceOfParent () + bool + IsDereferenceOfParent() override { return m_is_deref_of_parent; } protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual bool - CanUpdateWithInvalidExecutionContext (); + LazyBool + CanUpdateWithInvalidExecutionContext() override; - virtual ClangASTType - GetClangTypeImpl () + CompilerType + GetCompilerTypeImpl() override { - return m_clang_type; + return m_compiler_type; } - ClangASTType m_clang_type; + CompilerType m_compiler_type; ConstString m_type_name; uint64_t m_byte_size; int32_t m_byte_offset; @@ -101,6 +103,7 @@ protected: uint8_t m_bitfield_bit_offset; bool m_is_base_class; bool m_is_deref_of_parent; + llvm::Optional m_can_update_with_invalid_exe_ctx; // // void @@ -110,8 +113,9 @@ protected: friend class ValueObject; friend class ValueObjectConstResult; friend class ValueObjectConstResultImpl; + ValueObjectChild (ValueObject &parent, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, uint64_t byte_size, int32_t byte_offset, @@ -119,11 +123,12 @@ protected: uint32_t bitfield_bit_offset, bool is_base_class, bool is_deref_of_parent, - AddressType child_ptr_or_ref_addr_type); + AddressType child_ptr_or_ref_addr_type, + uint64_t language_flags); DISALLOW_COPY_AND_ASSIGN (ValueObjectChild); }; } // namespace lldb_private -#endif // liblldb_ValueObjectChild_h_ +#endif // liblldb_ValueObjectChild_h_ diff --git a/include/lldb/Core/ValueObjectConstResult.h b/include/lldb/Core/ValueObjectConstResult.h index 4e05d50132ec..f63ee83284df 100644 --- a/include/lldb/Core/ValueObjectConstResult.h +++ b/include/lldb/Core/ValueObjectConstResult.h @@ -26,6 +26,8 @@ namespace lldb_private { class ValueObjectConstResult : public ValueObject { public: + ~ValueObjectConstResult() override; + static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, @@ -34,14 +36,14 @@ public: static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const DataExtractor &data, lldb::addr_t address = LLDB_INVALID_ADDRESS); static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const lldb::DataBufferSP &result_data_sp, lldb::ByteOrder byte_order, @@ -50,7 +52,7 @@ public: static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, lldb::addr_t address, AddressType address_type, @@ -67,76 +69,76 @@ public: Create (ExecutionContextScope *exe_scope, const Error& error); - virtual ~ValueObjectConstResult(); - - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual bool - IsInScope (); + bool + IsInScope() override; void SetByteSize (size_t size); - virtual lldb::ValueObjectSP - Dereference (Error &error); + lldb::ValueObjectSP + Dereference(Error &error) override; - virtual ValueObject * - CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + ValueObject * + CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; - virtual lldb::ValueObjectSP - GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) override; - virtual lldb::ValueObjectSP - AddressOf (Error &error); + lldb::ValueObjectSP + AddressOf(Error &error) override; - virtual lldb::addr_t - GetAddressOf (bool scalar_is_load_address = true, - AddressType *address_type = NULL); + lldb::addr_t + GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr) override; - virtual size_t - GetPointeeData (DataExtractor& data, - uint32_t item_idx = 0, - uint32_t item_count = 1); + size_t + GetPointeeData(DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1) override; - virtual lldb::addr_t - GetLiveAddress() + lldb::addr_t + GetLiveAddress() override { return m_impl.GetLiveAddress(); } - virtual void + void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, - AddressType address_type = eAddressTypeLoad) + AddressType address_type = eAddressTypeLoad) override { - m_impl.SetLiveAddress(addr, - address_type); + m_impl.SetLiveAddress(addr, address_type); } - virtual lldb::ValueObjectSP - GetDynamicValue (lldb::DynamicValueType valueType); + lldb::ValueObjectSP + GetDynamicValue(lldb::DynamicValueType valueType) override; - virtual lldb::LanguageType - GetPreferredDisplayLanguage (); + lldb::LanguageType + GetPreferredDisplayLanguage() override; + + lldb::ValueObjectSP + Cast(const CompilerType &compiler_type) override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; ConstString m_type_name; uint64_t m_byte_size; @@ -145,19 +147,20 @@ protected: private: friend class ValueObjectConstResultImpl; + ValueObjectConstResult (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const DataExtractor &data, lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const lldb::DataBufferSP &result_data_sp, lldb::ByteOrder byte_order, @@ -165,7 +168,7 @@ private: lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, lldb::addr_t address, AddressType address_type, @@ -184,4 +187,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectConstResult_h_ +#endif // liblldb_ValueObjectConstResult_h_ diff --git a/include/lldb/Core/ValueObjectConstResultCast.h b/include/lldb/Core/ValueObjectConstResultCast.h new file mode 100644 index 000000000000..395820dad6c7 --- /dev/null +++ b/include/lldb/Core/ValueObjectConstResultCast.h @@ -0,0 +1,76 @@ +//===-- ValueObjectConstResultCast.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_ValueObjectConstResultCast_h_ +#define liblldb_ValueObjectConstResultCast_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObjectCast.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" + +namespace lldb_private { + +class ValueObjectConstResultCast : public ValueObjectCast +{ +public: + ValueObjectConstResultCast ( + ValueObject &parent, + const ConstString &name, + const CompilerType &cast_type, + lldb::addr_t live_address = LLDB_INVALID_ADDRESS); + + ~ValueObjectConstResultCast() override; + + lldb::ValueObjectSP + Dereference(Error &error) override; + + ValueObject * + CreateChildAtIndex(size_t idx, + bool synthetic_array_member, + int32_t synthetic_index) override; + + virtual CompilerType + GetCompilerType () + { + return ValueObjectCast::GetCompilerType(); + } + + lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, + const CompilerType& type, + bool can_create) override; + + lldb::ValueObjectSP + AddressOf (Error &error) override; + + size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1) override; + + lldb::ValueObjectSP + Cast (const CompilerType &compiler_type) override; + +protected: + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultCast); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultCast_h_ diff --git a/include/lldb/Core/ValueObjectConstResultChild.h b/include/lldb/Core/ValueObjectConstResultChild.h index 9063276b0198..356d175a64ae 100644 --- a/include/lldb/Core/ValueObjectConstResultChild.h +++ b/include/lldb/Core/ValueObjectConstResultChild.h @@ -27,39 +27,44 @@ class ValueObjectConstResultChild : public ValueObjectChild public: ValueObjectConstResultChild (ValueObject &parent, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, uint32_t byte_size, int32_t byte_offset, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool is_base_class, - bool is_deref_of_parent); + bool is_deref_of_parent, + lldb::addr_t live_address, + uint64_t language_flags); - virtual ~ValueObjectConstResultChild(); + ~ValueObjectConstResultChild() override; - virtual lldb::ValueObjectSP - Dereference (Error &error); + lldb::ValueObjectSP + Dereference(Error &error) override; - virtual ValueObject * - CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + ValueObject * + CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; - virtual ClangASTType - GetClangType () + virtual CompilerType + GetCompilerType () { - return ValueObjectChild::GetClangType(); + return ValueObjectChild::GetCompilerType(); } - virtual lldb::ValueObjectSP - GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) override; - virtual lldb::ValueObjectSP - AddressOf (Error &error); + lldb::ValueObjectSP + AddressOf (Error &error) override; - virtual size_t + size_t GetPointeeData (DataExtractor& data, uint32_t item_idx = 0, - uint32_t item_count = 1); + uint32_t item_count = 1) override; + + lldb::ValueObjectSP + Cast (const CompilerType &compiler_type) override; protected: ValueObjectConstResultImpl m_impl; @@ -74,4 +79,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectConstResultChild_h_ +#endif // liblldb_ValueObjectConstResultChild_h_ diff --git a/include/lldb/Core/ValueObjectConstResultImpl.h b/include/lldb/Core/ValueObjectConstResultImpl.h index e3574e8a4d4e..36b82f00a240 100644 --- a/include/lldb/Core/ValueObjectConstResultImpl.h +++ b/include/lldb/Core/ValueObjectConstResultImpl.h @@ -1,4 +1,4 @@ -//===-- ValueObjectConstResultImpl.h -----------------------------*- C++ -*-===// +//===-- ValueObjectConstResultImpl.h ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,15 +26,12 @@ namespace lldb_private { class ValueObjectConstResultImpl { public: - ValueObjectConstResultImpl (ValueObject* valobj, lldb::addr_t live_address = LLDB_INVALID_ADDRESS); - + virtual - ~ValueObjectConstResultImpl() - { - } - + ~ValueObjectConstResultImpl() = default; + lldb::ValueObjectSP Dereference (Error &error); @@ -42,7 +39,7 @@ public: CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); lldb::ValueObjectSP - GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create); + GetSyntheticChildAtOffset (uint32_t offset, const CompilerType& type, bool can_create); lldb::ValueObjectSP AddressOf (Error &error); @@ -52,6 +49,9 @@ public: { return m_live_address; } + + lldb::ValueObjectSP + Cast (const CompilerType &compiler_type); void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, @@ -62,16 +62,15 @@ public: } virtual lldb::addr_t - GetAddressOf (bool scalar_is_load_address = true, - AddressType *address_type = NULL); + GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr); virtual size_t - GetPointeeData (DataExtractor& data, - uint32_t item_idx = 0, - uint32_t item_count = 1); + GetPointeeData(DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); private: - ValueObject *m_impl_backend; lldb::addr_t m_live_address; AddressType m_live_address_type; @@ -83,4 +82,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectConstResultImpl_h_ +#endif // liblldb_ValueObjectConstResultImpl_h_ diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h index 8d42706be166..80f37f104765 100644 --- a/include/lldb/Core/ValueObjectDynamicValue.h +++ b/include/lldb/Core/ValueObjectDynamicValue.h @@ -1,4 +1,4 @@ -//===-- ValueObjectDynamicValue.h -----------------------------------*- C++ -*-===// +//===-- ValueObjectDynamicValue.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,109 +26,131 @@ namespace lldb_private { class ValueObjectDynamicValue : public ValueObject { public: - virtual - ~ValueObjectDynamicValue(); + ~ValueObjectDynamicValue() override; - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual bool - IsDynamic () + bool + IsDynamic() override { return true; } - virtual bool - GetIsConstant () const + bool + IsBaseClass () override { + if (m_parent) + return m_parent->IsBaseClass(); return false; } - virtual ValueObject * - GetParent() + bool + GetIsConstant() const override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return false; + } + + ValueObject * + GetParent() override + { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } - virtual const ValueObject * - GetParent() const + const ValueObject * + GetParent() const override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } - virtual lldb::ValueObjectSP - GetStaticValue () + lldb::ValueObjectSP + GetStaticValue() override { return m_parent->GetSP(); } - + void SetOwningSP (lldb::ValueObjectSP &owning_sp) { if (m_owning_valobj_sp == owning_sp) return; - assert (m_owning_valobj_sp.get() == NULL); + assert (m_owning_valobj_sp.get() == nullptr); m_owning_valobj_sp = owning_sp; } - virtual bool - SetValueFromCString (const char *value_str, Error& error); + bool + SetValueFromCString(const char *value_str, Error& error) override; + + bool + SetData(DataExtractor &data, Error &error) override; + + TypeImpl + GetTypeImpl() override; + + lldb::VariableSP + GetVariable () override + { + return m_parent ? m_parent->GetVariable() : nullptr; + } + + lldb::LanguageType + GetPreferredDisplayLanguage() override; - virtual bool - SetData (DataExtractor &data, Error &error); + void + SetPreferredDisplayLanguage (lldb::LanguageType); + + bool + GetDeclaration(Declaration &decl) override; - virtual TypeImpl - GetTypeImpl (); + uint64_t + GetLanguageFlags () override; + void + SetLanguageFlags (uint64_t flags) override; + protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual bool - CanUpdateWithInvalidExecutionContext () + LazyBool + CanUpdateWithInvalidExecutionContext() override { - return true; + return eLazyBoolYes; } - virtual lldb::DynamicValueType - GetDynamicValueTypeImpl () + lldb::DynamicValueType + GetDynamicValueTypeImpl() override { return m_use_dynamic; } - virtual bool - HasDynamicValueTypeInfo () + bool + HasDynamicValueTypeInfo() override { return true; } - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; Address m_address; ///< The variable that this value object is based upon TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name @@ -141,12 +163,9 @@ private: friend class ValueObjectConstResult; ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic); - //------------------------------------------------------------------ - // For ValueObject only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (ValueObjectDynamicValue); }; } // namespace lldb_private -#endif // liblldb_ValueObjectDynamicValue_h_ +#endif // liblldb_ValueObjectDynamicValue_h_ diff --git a/include/lldb/Core/ValueObjectList.h b/include/lldb/Core/ValueObjectList.h index 6565367cc61c..4f5e7b246fbd 100644 --- a/include/lldb/Core/ValueObjectList.h +++ b/include/lldb/Core/ValueObjectList.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/UserID.h" #include "lldb/Target/ExecutionContextScope.h" diff --git a/include/lldb/Core/ValueObjectMemory.h b/include/lldb/Core/ValueObjectMemory.h index 41b43188a46a..0e12fc7e3f28 100644 --- a/include/lldb/Core/ValueObjectMemory.h +++ b/include/lldb/Core/ValueObjectMemory.h @@ -15,7 +15,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/ValueObject.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" namespace lldb_private { @@ -26,6 +26,8 @@ namespace lldb_private { class ValueObjectMemory : public ValueObject { public: + ~ValueObjectMemory() override; + static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, const char *name, @@ -36,42 +38,39 @@ public: Create (ExecutionContextScope *exe_scope, const char *name, const Address &address, - const ClangASTType &ast_type); - - virtual - ~ValueObjectMemory(); + const CompilerType &ast_type); - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual lldb::ModuleSP - GetModule(); + lldb::ModuleSP + GetModule() override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; Address m_address; ///< The variable that this value object is based upon lldb::TypeSP m_type_sp; - ClangASTType m_clang_type; + CompilerType m_compiler_type; private: ValueObjectMemory (ExecutionContextScope *exe_scope, @@ -82,7 +81,7 @@ private: ValueObjectMemory (ExecutionContextScope *exe_scope, const char *name, const Address &address, - const ClangASTType &ast_type); + const CompilerType &ast_type); //------------------------------------------------------------------ // For ValueObject only //------------------------------------------------------------------ @@ -91,4 +90,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectMemory_h_ +#endif // liblldb_ValueObjectMemory_h_ diff --git a/include/lldb/Core/ValueObjectRegister.h b/include/lldb/Core/ValueObjectRegister.h index f7c7683d60bc..ac76f9e4280b 100644 --- a/include/lldb/Core/ValueObjectRegister.h +++ b/include/lldb/Core/ValueObjectRegister.h @@ -27,40 +27,38 @@ namespace lldb_private { class ValueObjectRegisterContext : public ValueObject { public: + ~ValueObjectRegisterContext() override; - virtual - ~ValueObjectRegisterContext(); + uint64_t + GetByteSize() override; - virtual uint64_t - GetByteSize(); - - virtual lldb::ValueType - GetValueType () const + lldb::ValueType + GetValueType() const override { return lldb::eValueTypeRegisterSet; } - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual ValueObject * - CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + ValueObject * + CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; lldb::RegisterContextSP m_reg_ctx_sp; @@ -75,46 +73,44 @@ private: class ValueObjectRegisterSet : public ValueObject { public: + ~ValueObjectRegisterSet() override; + static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); - virtual - ~ValueObjectRegisterSet(); - - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual lldb::ValueType - GetValueType () const + lldb::ValueType + GetValueType() const override { return lldb::eValueTypeRegisterSet; } - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual ValueObject * - CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + ValueObject * + CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; - virtual lldb::ValueObjectSP - GetChildMemberWithName (const ConstString &name, bool can_create); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); + lldb::ValueObjectSP + GetChildMemberWithName(const ConstString &name, bool can_create) override; + size_t + GetIndexOfChildWithName(const ConstString &name) override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; lldb::RegisterContextSP m_reg_ctx_sp; const RegisterSet *m_reg_set; @@ -122,6 +118,7 @@ protected: private: friend class ValueObjectRegisterContext; + ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); //------------------------------------------------------------------ @@ -133,57 +130,58 @@ private: class ValueObjectRegister : public ValueObject { public: + ~ValueObjectRegister() override; + static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); - virtual - ~ValueObjectRegister(); - - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual lldb::ValueType - GetValueType () const + lldb::ValueType + GetValueType() const override { return lldb::eValueTypeRegister; } - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual bool - SetValueFromCString (const char *value_str, Error& error); + bool + SetValueFromCString(const char *value_str, Error& error) override; - virtual bool - SetData (DataExtractor &data, Error &error); + bool + SetData(DataExtractor &data, Error &error) override; - virtual bool - ResolveValue (Scalar &scalar); + bool + ResolveValue(Scalar &scalar) override; - virtual void - GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat = eGetExpressionPathFormatDereferencePointers); + void + GetExpressionPath(Stream &s, bool qualify_cxx_base_classes, + GetExpressionPathFormat epformat = eGetExpressionPathFormatDereferencePointers) override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; lldb::RegisterContextSP m_reg_ctx_sp; RegisterInfo m_reg_info; RegisterValue m_reg_value; ConstString m_type_name; - ClangASTType m_clang_type; + CompilerType m_compiler_type; private: void ConstructObject (uint32_t reg_num); friend class ValueObjectRegisterSet; + ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); @@ -195,4 +193,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectRegister_h_ +#endif // liblldb_ValueObjectRegister_h_ diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h index 88824ef4fa54..05bc3781a3cc 100644 --- a/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -1,4 +1,4 @@ -//===-- ValueObjectSyntheticFilter.h -------------------------------*- C++ -*-===// +//===-- ValueObjectSyntheticFilter.h ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,7 +12,8 @@ // C Includes // C++ Includes -#include +#include + // Other libraries and framework includes // Project includes #include "lldb/Core/ThreadSafeSTLMap.h" @@ -30,140 +31,142 @@ namespace lldb_private { class ValueObjectSynthetic : public ValueObject { public: - virtual - ~ValueObjectSynthetic(); + ~ValueObjectSynthetic() override; - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual bool - MightHaveChildren(); + bool + MightHaveChildren() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx, bool can_create); + lldb::ValueObjectSP + GetChildAtIndex(size_t idx, bool can_create) override; - virtual lldb::ValueObjectSP - GetChildMemberWithName (const ConstString &name, bool can_create); + lldb::ValueObjectSP + GetChildMemberWithName(const ConstString &name, bool can_create) override; - virtual size_t - GetIndexOfChildWithName (const ConstString &name); + size_t + GetIndexOfChildWithName(const ConstString &name) override; - virtual lldb::ValueObjectSP - GetDynamicValue (lldb::DynamicValueType valueType); + lldb::ValueObjectSP + GetDynamicValue(lldb::DynamicValueType valueType) override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual bool - HasSyntheticValue() + bool + HasSyntheticValue() override { return false; } - virtual bool - IsSynthetic() { return true; } + bool + IsSynthetic() override + { + return true; + } - virtual void - CalculateSyntheticValue (bool use_synthetic) + void + CalculateSyntheticValue(bool use_synthetic) override { } - virtual bool - IsDynamic () + bool + IsDynamic() override { - if (m_parent) - return m_parent->IsDynamic(); - else - return false; + return ((m_parent != nullptr) ? m_parent->IsDynamic() : false); } - virtual lldb::ValueObjectSP - GetStaticValue () + lldb::ValueObjectSP + GetStaticValue() override { - if (m_parent) - return m_parent->GetStaticValue(); - else - return GetSP(); + return ((m_parent != nullptr) ? m_parent->GetStaticValue() : GetSP()); } virtual lldb::DynamicValueType GetDynamicValueType () { - if (m_parent) - return m_parent->GetDynamicValueType(); - else - return lldb::eNoDynamicValues; + return ((m_parent != nullptr) ? m_parent->GetDynamicValueType() : lldb::eNoDynamicValues); } - virtual ValueObject * - GetParent() + ValueObject * + GetParent() override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } - virtual const ValueObject * - GetParent() const + const ValueObject * + GetParent() const override { - if (m_parent) - return m_parent->GetParent(); - else - return NULL; + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); } - virtual lldb::ValueObjectSP - GetNonSyntheticValue (); + lldb::ValueObjectSP + GetNonSyntheticValue() override; - virtual bool - CanProvideValue (); + bool + CanProvideValue() override; - virtual bool - DoesProvideSyntheticValue () + bool + DoesProvideSyntheticValue() override { return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes); } - virtual bool - GetIsConstant () const + bool + GetIsConstant() const override { return false; } - virtual bool - SetValueFromCString (const char *value_str, Error& error); + bool + SetValueFromCString(const char *value_str, Error& error) override; - virtual void - SetFormat (lldb::Format format); + void + SetFormat(lldb::Format format) override; + + lldb::LanguageType + GetPreferredDisplayLanguage() override; + + void + SetPreferredDisplayLanguage (lldb::LanguageType); + + bool + GetDeclaration(Declaration &decl) override; + + uint64_t + GetLanguageFlags () override; + + void + SetLanguageFlags (uint64_t flags) override; protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual bool - CanUpdateWithInvalidExecutionContext () + LazyBool + CanUpdateWithInvalidExecutionContext() override { - return true; + return eLazyBoolYes; } - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; virtual void CreateSynthFilter (); @@ -195,12 +198,9 @@ private: void CopyValueData (ValueObject *source); - //------------------------------------------------------------------ - // For ValueObject only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (ValueObjectSynthetic); }; } // namespace lldb_private -#endif // liblldb_ValueObjectSyntheticFilter_h_ +#endif // liblldb_ValueObjectSyntheticFilter_h_ diff --git a/include/lldb/Core/ValueObjectVariable.h b/include/lldb/Core/ValueObjectVariable.h index 0e32d09057dc..4adb6bad0ada 100644 --- a/include/lldb/Core/ValueObjectVariable.h +++ b/include/lldb/Core/ValueObjectVariable.h @@ -25,61 +25,66 @@ namespace lldb_private { class ValueObjectVariable : public ValueObject { public: + ~ValueObjectVariable() override; + static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); - virtual - ~ValueObjectVariable(); - - virtual uint64_t - GetByteSize(); + uint64_t + GetByteSize() override; - virtual ConstString - GetTypeName(); + ConstString + GetTypeName() override; - virtual ConstString - GetQualifiedTypeName(); + ConstString + GetQualifiedTypeName() override; - virtual ConstString - GetDisplayTypeName(); + ConstString + GetDisplayTypeName() override; - virtual size_t - CalculateNumChildren(); + size_t + CalculateNumChildren(uint32_t max) override; - virtual lldb::ValueType - GetValueType() const; + lldb::ValueType + GetValueType() const override; - virtual bool - IsInScope (); + bool + IsInScope() override; - virtual lldb::ModuleSP - GetModule(); + lldb::ModuleSP + GetModule() override; - virtual SymbolContextScope * - GetSymbolContextScope(); + SymbolContextScope * + GetSymbolContextScope() override; - virtual bool - GetDeclaration (Declaration &decl); + bool + GetDeclaration(Declaration &decl) override; - virtual const char * - GetLocationAsCString (); + const char * + GetLocationAsCString() override; - virtual bool - SetValueFromCString (const char *value_str, Error& error); + bool + SetValueFromCString(const char *value_str, Error& error) override; - virtual bool - SetData (DataExtractor &data, Error &error); + bool + SetData(DataExtractor &data, Error &error) override; + + virtual lldb::VariableSP + GetVariable () override + { + return m_variable_sp; + } protected: - virtual bool - UpdateValue (); + bool + UpdateValue() override; - virtual ClangASTType - GetClangTypeImpl (); + CompilerType + GetCompilerTypeImpl() override; lldb::VariableSP m_variable_sp; ///< The variable that this value object is based upon Value m_resolved_value; ///< The value that DWARFExpression resolves this variable to before we patch it up - + private: ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); //------------------------------------------------------------------ @@ -90,4 +95,4 @@ private: } // namespace lldb_private -#endif // liblldb_ValueObjectVariable_h_ +#endif // liblldb_ValueObjectVariable_h_ diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h index 9fa8816229a9..649a93154b3f 100644 --- a/include/lldb/Core/dwarf.h +++ b/include/lldb/Core/dwarf.h @@ -14,13 +14,16 @@ // Get the DWARF constant definitions from llvm #include "llvm/Support/Dwarf.h" + +#include "lldb/Core/RangeMap.h" + // and stuff them in our default namespace using namespace llvm::dwarf; typedef uint32_t dw_uleb128_t; typedef int32_t dw_sleb128_t; typedef uint16_t dw_attr_t; -typedef uint8_t dw_form_t; +typedef uint16_t dw_form_t; typedef uint16_t dw_tag_t; typedef uint64_t dw_addr_t; // Dwarf address define that must be big enough for any addresses in the compile units that get parsed @@ -59,5 +62,6 @@ typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for //#define DW_OP_APPLE_clear 0xFE // clears the entire expression stack, ok if the stack is empty //#define DW_OP_APPLE_error 0xFF // Stops expression evaluation and returns an error (no args) +typedef lldb_private::RangeArray DWARFRangeList; #endif // DebugBase_dwarf_h_ diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h deleted file mode 100644 index a175e1a4d164..000000000000 --- a/include/lldb/DataFormatters/CXXFormatterFunctions.h +++ /dev/null @@ -1,375 +0,0 @@ -//===-- CXXFormatterFunctions.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_CXXFormatterFunctions_h_ -#define liblldb_CXXFormatterFunctions_h_ - -#include -#include - -#include "lldb/lldb-forward.h" - -#include "lldb/Core/ConstString.h" -#include "lldb/DataFormatters/FormatClasses.h" -#include "lldb/DataFormatters/TypeSynthetic.h" -#include "lldb/DataFormatters/VectorType.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -#include "clang/AST/ASTContext.h" - -namespace lldb_private { - namespace formatters - { - StackFrame* - GetViableFrame (ExecutionContext exe_ctx); - - bool - ExtractValueFromObjCExpression (ValueObject &valobj, - const char* target_type, - const char* selector, - uint64_t &value); - - bool - ExtractSummaryFromObjCExpression (ValueObject &valobj, - const char* target_type, - const char* selector, - Stream &stream); - - lldb::ValueObjectSP - CallSelectorOnObject (ValueObject &valobj, - const char* return_type, - const char* selector, - uint64_t index); - - lldb::ValueObjectSP - CallSelectorOnObject (ValueObject &valobj, - const char* return_type, - const char* selector, - const char* key); - - size_t - ExtractIndexFromString (const char* item_name); - - time_t - GetOSXEpoch (); - - bool - FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // C++ function pointer - - bool - Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar* - - bool - Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t* - - bool - WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t* - - bool - Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar - - bool - Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t - - bool - WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t - - bool - LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string - - bool - LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring - - bool - LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<> - - bool - ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - template - bool - NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - template - bool - NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - template - bool - NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream); - - bool - NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - template - bool - ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - bool - RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - extern template bool - NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - - extern template bool - NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - - extern template bool - NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - - extern template bool - NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - - extern template bool - ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); - - extern template bool - ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); - - bool - CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxVectorBoolSyntheticFrontEnd (); - private: - ClangASTType m_bool_type; - ExecutionContextRef m_exe_ctx_ref; - uint64_t m_count; - lldb::addr_t m_base_data_address; - std::map m_children; - }; - - SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - bool - LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - - class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibstdcppMapIteratorSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - lldb::addr_t m_pair_address; - ClangASTType m_pair_type; - EvaluateExpressionOptions m_options; - lldb::ValueObjectSP m_pair_sp; - }; - - SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibCxxMapIteratorSyntheticFrontEnd (); - private: - ValueObject *m_pair_ptr; - }; - - SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, - ConstString item_name); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~VectorIteratorSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - ConstString m_item_name; - lldb::ValueObjectSP m_item_sp; - }; - - SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxSharedPtrSyntheticFrontEnd (); - private: - ValueObject* m_cntrl; - lldb::ValueObjectSP m_count_sp; - lldb::ValueObjectSP m_weak_count_sp; - uint8_t m_ptr_size; - lldb::ByteOrder m_byte_order; - }; - - SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - - SyntheticChildrenFrontEnd* VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - } // namespace formatters -} // namespace lldb_private - -#endif // liblldb_CXXFormatterFunctions_h_ diff --git a/include/lldb/DataFormatters/CXXFunctionPointer.h b/include/lldb/DataFormatters/CXXFunctionPointer.h new file mode 100644 index 000000000000..eaa39582eaaa --- /dev/null +++ b/include/lldb/DataFormatters/CXXFunctionPointer.h @@ -0,0 +1,23 @@ +//===-- CXXFunctionPointer.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_CXXFunctionPointer_h_ +#define liblldb_CXXFunctionPointer_h_ + +#include "lldb/lldb-forward.h" + +namespace lldb_private { + namespace formatters + { + bool + CXXFunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); + } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CXXFunctionPointer_h_ diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h index a0b2e58bba28..856156670c96 100644 --- a/include/lldb/DataFormatters/DataVisualization.h +++ b/include/lldb/DataFormatters/DataVisualization.h @@ -1,4 +1,4 @@ -//===-- DataVisualization.h ----------------------------------------*- C++ -*-===// +//===-- DataVisualization.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -28,7 +28,6 @@ namespace lldb_private { class DataVisualization { public: - // use this call to force the FM to consider itself updated even when there is no apparent reason for that static void ForceUpdate(); @@ -83,8 +82,8 @@ public: AnyMatches(ConstString type_name, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, - const char** matching_category = NULL, - TypeCategoryImpl::FormatCategoryItems* matching_type = NULL); + const char** matching_category = nullptr, + TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr); class NamedSummaryFormats { @@ -102,7 +101,7 @@ public: Clear (); static void - LoopThrough (TypeSummaryImpl::SummaryCallback callback, void* callback_baton); + ForEach (std::function callback); static uint32_t GetCount (); @@ -111,12 +110,15 @@ public: class Categories { public: - static bool GetCategory (const ConstString &category, lldb::TypeCategoryImplSP &entry, bool allow_create = true); + static bool + GetCategory (lldb::LanguageType language, + lldb::TypeCategoryImplSP &entry); + static void Add (const ConstString &category); @@ -133,8 +135,14 @@ public: Enable (const ConstString& category, TypeCategoryMap::Position = TypeCategoryMap::Default); + static void + Enable (lldb::LanguageType lang_type); + static void Disable (const ConstString& category); + + static void + Disable (lldb::LanguageType lang_type); static void Enable (const lldb::TypeCategoryImplSP& category, @@ -150,7 +158,7 @@ public: DisableStar (); static void - LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton); + ForEach (TypeCategoryMap::ForEachCallback callback); static uint32_t GetCount (); @@ -160,7 +168,6 @@ public: }; }; - } // namespace lldb_private -#endif // lldb_DataVisualization_h_ +#endif// lldb_DataVisualization_h_ diff --git a/include/lldb/DataFormatters/DumpValueObjectOptions.h b/include/lldb/DataFormatters/DumpValueObjectOptions.h new file mode 100644 index 000000000000..f65ee7b95845 --- /dev/null +++ b/include/lldb/DataFormatters/DumpValueObjectOptions.h @@ -0,0 +1,185 @@ +//===-- DumpValueObjectOptions.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_DumpValueObjectOptions_h_ +#define lldb_DumpValueObjectOptions_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-public.h" + +#include +#include + +namespace lldb_private { + +class DumpValueObjectOptions +{ +public: + struct PointerDepth + { + enum class Mode + { + Always, + Formatters, + Default, + Never + } m_mode; + uint32_t m_count; + + PointerDepth + operator --() const + { + if (m_count > 0) + return PointerDepth {m_mode,m_count-1}; + return PointerDepth {m_mode,m_count}; + } + + bool + CanAllowExpansion () const; + + bool + CanAllowExpansion (bool is_root, + TypeSummaryImpl* entry, + ValueObject *valobj, + const std::string& summary); + }; + + typedef std::function DeclPrintingHelper; + + static const DumpValueObjectOptions + DefaultOptions() + { + static DumpValueObjectOptions g_default_options; + + return g_default_options; + } + + DumpValueObjectOptions(); + + DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default; + + DumpValueObjectOptions (ValueObject& valobj); + + DumpValueObjectOptions& + SetMaximumPointerDepth(PointerDepth depth = {PointerDepth::Mode::Never,0}); + + DumpValueObjectOptions& + SetMaximumDepth(uint32_t depth = 0); + + DumpValueObjectOptions& + SetDeclPrintingHelper(DeclPrintingHelper helper); + + DumpValueObjectOptions& + SetShowTypes(bool show = false); + + DumpValueObjectOptions& + SetShowLocation(bool show = false); + + DumpValueObjectOptions& + SetUseObjectiveC(bool use = false); + + DumpValueObjectOptions& + SetShowSummary(bool show = true); + + DumpValueObjectOptions& + SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues); + + DumpValueObjectOptions& + SetUseSyntheticValue(bool use_synthetic = true); + + DumpValueObjectOptions& + SetScopeChecked(bool check = true); + + DumpValueObjectOptions& + SetFlatOutput(bool flat = false); + + DumpValueObjectOptions& + SetOmitSummaryDepth(uint32_t depth = 0); + + DumpValueObjectOptions& + SetIgnoreCap(bool ignore = false); + + DumpValueObjectOptions& + SetRawDisplay(); + + DumpValueObjectOptions& + SetFormat (lldb::Format format = lldb::eFormatDefault); + + DumpValueObjectOptions& + SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP()); + + DumpValueObjectOptions& + SetRootValueObjectName(const char* name = nullptr); + + DumpValueObjectOptions& + SetHideRootType (bool hide_root_type = false); + + DumpValueObjectOptions& + SetHideName (bool hide_name = false); + + DumpValueObjectOptions& + SetHideValue (bool hide_value = false); + + DumpValueObjectOptions& + SetHidePointerValue (bool hide = false); + + DumpValueObjectOptions& + SetVariableFormatDisplayLanguage (lldb::LanguageType lang = lldb::eLanguageTypeUnknown); + + DumpValueObjectOptions& + SetRunValidator (bool run = true); + + DumpValueObjectOptions& + SetUseTypeDisplayName (bool dis = false); + + DumpValueObjectOptions& + SetAllowOnelinerMode (bool oneliner = false); + + DumpValueObjectOptions& + SetRevealEmptyAggregates (bool reveal = true); + +public: + uint32_t m_max_depth = UINT32_MAX; + lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; + uint32_t m_omit_summary_depth = 0; + lldb::Format m_format = lldb::eFormatDefault; + lldb::TypeSummaryImplSP m_summary_sp; + std::string m_root_valobj_name; + lldb::LanguageType m_varformat_language = lldb::eLanguageTypeUnknown; + PointerDepth m_max_ptr_depth; + DeclPrintingHelper m_decl_printing_helper; + bool m_use_synthetic : 1; + bool m_scope_already_checked : 1; + bool m_flat_output : 1; + bool m_ignore_cap : 1; + bool m_show_types : 1; + bool m_show_location : 1; + bool m_use_objc : 1; + bool m_hide_root_type : 1; + bool m_hide_name : 1; + bool m_hide_value : 1; + bool m_run_validator : 1; + bool m_use_type_display_name : 1; + bool m_allow_oneliner_mode : 1; + bool m_hide_pointer_value : 1; + bool m_reveal_empty_aggregates : 1; +}; + +} // namespace lldb_private + +#endif // lldb_DumpValueObjectOptions_h_ diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h index fa46306e5404..9f1e078f7199 100644 --- a/include/lldb/DataFormatters/FormatCache.h +++ b/include/lldb/DataFormatters/FormatCache.h @@ -19,7 +19,6 @@ #include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" #include "lldb/Host/Mutex.h" -#include "lldb/DataFormatters/FormatClasses.h" namespace lldb_private { class FormatCache diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h index 651160371c69..b5ac41c2bd6e 100644 --- a/include/lldb/DataFormatters/FormatClasses.h +++ b/include/lldb/DataFormatters/FormatClasses.h @@ -10,25 +10,45 @@ #ifndef lldb_FormatClasses_h_ #define lldb_FormatClasses_h_ +// C Includes // C++ Includes +#include +#include #include #include // Other libraries and framework includes - // Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" - -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/DataFormatters/TypeFormat.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/DataFormatters/TypeValidator.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" namespace lldb_private { +class HardcodedFormatters { +public: + template + using HardcodedFormatterFinder = std::function; + + template + using HardcodedFormatterFinders = std::vector>; + + typedef HardcodedFormatterFinders HardcodedFormatFinder; + typedef HardcodedFormatterFinders HardcodedSummaryFinder; + typedef HardcodedFormatterFinders HardcodedSyntheticFinder; + typedef HardcodedFormatterFinders HardcodedValidatorFinder; +}; + class FormattersMatchCandidate { public: - FormattersMatchCandidate (ConstString name, uint32_t reason, bool strip_ptr, @@ -41,10 +61,9 @@ public: m_stripped_typedef(strip_tydef) { } - - ~FormattersMatchCandidate () - {} - + + ~FormattersMatchCandidate() = default; + ConstString GetTypeName () const { @@ -99,6 +118,36 @@ private: }; typedef std::vector FormattersMatchVector; +typedef std::vector CandidateLanguagesVector; + +class FormattersMatchData +{ +public: + FormattersMatchData (ValueObject&, + lldb::DynamicValueType); + + FormattersMatchVector + GetMatchesVector (); + + ConstString + GetTypeForCache (); + + CandidateLanguagesVector + GetCandidateLanguages (); + + ValueObject& + GetValueObject (); + + lldb::DynamicValueType + GetDynamicValueType (); + +private: + ValueObject& m_valobj; + lldb::DynamicValueType m_dynamic_value_type; + std::pair m_formatters_match_vector; + ConstString m_type_for_cache; + CandidateLanguagesVector m_candidate_languages; +}; class TypeNameSpecifierImpl { @@ -130,7 +179,7 @@ public: } } - TypeNameSpecifierImpl (ClangASTType type) : + TypeNameSpecifierImpl (CompilerType type) : m_is_regex(false), m_type() { @@ -146,7 +195,7 @@ public: { if (m_type.m_type_name.size()) return m_type.m_type_name.c_str(); - return NULL; + return nullptr; } lldb::TypeSP @@ -157,12 +206,12 @@ public: return lldb::TypeSP(); } - ClangASTType - GetClangASTType () + CompilerType + GetCompilerType () { if (m_type.m_type_pair.IsValid()) - return m_type.m_type_pair.GetClangASTType(); - return ClangASTType(); + return m_type.m_type_pair.GetCompilerType(); + return CompilerType(); } bool @@ -174,19 +223,18 @@ public: private: bool m_is_regex; // this works better than TypeAndOrName because the latter only wraps a TypeSP - // whereas TypePair can also be backed by a ClangASTType + // whereas TypePair can also be backed by a CompilerType struct TypeOrName { std::string m_type_name; TypePair m_type_pair; }; TypeOrName m_type; - - + private: DISALLOW_COPY_AND_ASSIGN(TypeNameSpecifierImpl); }; } // namespace lldb_private -#endif // lldb_FormatClasses_h_ +#endif // lldb_FormatClasses_h_ diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h index a1f4b59fb344..24ba5a7f0aa5 100644 --- a/include/lldb/DataFormatters/FormatManager.h +++ b/include/lldb/DataFormatters/FormatManager.h @@ -1,4 +1,4 @@ -//===-- FormatManager.h -------------------------------------------*- C++ -*-===// +//===-- FormatManager.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,10 @@ // C Includes // C++ Includes +#include +#include +#include +#include // Other libraries and framework includes // Project includes @@ -21,12 +25,10 @@ #include "lldb/DataFormatters/FormatCache.h" #include "lldb/DataFormatters/FormatClasses.h" #include "lldb/DataFormatters/FormattersContainer.h" +#include "lldb/DataFormatters/LanguageCategory.h" #include "lldb/DataFormatters/TypeCategory.h" #include "lldb/DataFormatters/TypeCategoryMap.h" -#include -#include - namespace lldb_private { // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization @@ -39,19 +41,12 @@ class FormatManager : public IFormatChangeListener typedef FormatMap NamedSummariesMap; typedef TypeCategoryMap::MapType::iterator CategoryMapIterator; public: + typedef std::map LanguageCategories; - template - using HardcodedFormatterFinder = std::function; - - template - using HardcodedFormatterFinders = std::vector>; - - typedef TypeCategoryMap::CallbackType CategoryCallback; - - FormatManager (); + FormatManager(); + ~FormatManager() override = default; + NamedSummariesMap& GetNamedSummaryContainer () { @@ -62,8 +57,34 @@ public: EnableCategory (const ConstString& category_name, TypeCategoryMap::Position pos = TypeCategoryMap::Default) { - m_categories_map.Enable(category_name, - pos); + EnableCategory(category_name, + pos, + std::initializer_list()); + } + + void + EnableCategory (const ConstString& category_name, + TypeCategoryMap::Position pos, + lldb::LanguageType lang) + { + std::initializer_list langs = {lang}; + EnableCategory(category_name, + pos, + langs); + } + + void + EnableCategory (const ConstString& category_name, + TypeCategoryMap::Position pos = TypeCategoryMap::Default, + std::initializer_list langs = {}) + { + TypeCategoryMap::ValueSP category_sp; + if (m_categories_map.Get(category_name, category_sp) && category_sp) + { + m_categories_map.Enable(category_sp, pos); + for (const lldb::LanguageType lang : langs) + category_sp->AddLanguage(lang); + } } void @@ -87,16 +108,10 @@ public: } void - EnableAllCategories () - { - m_categories_map.EnableAllCategories (); - } + EnableAllCategories (); void - DisableAllCategories () - { - m_categories_map.DisableAllCategories (); - } + DisableAllCategories (); bool DeleteCategory (const ConstString& category_name) @@ -123,14 +138,11 @@ public: } void - LoopThroughCategories (CategoryCallback callback, void* param) - { - m_categories_map.LoopThrough(callback, param); - } + ForEachCategory (TypeCategoryMap::ForEachCallback callback); lldb::TypeCategoryImplSP - GetCategory (const char* category_name = NULL, - bool can_create = true) + GetCategory(const char* category_name = nullptr, + bool can_create = true) { if (!category_name) return GetCategory(m_default_category_name); @@ -182,11 +194,11 @@ public: lldb::DynamicValueType use_dynamic); bool - AnyMatches (ConstString type_name, - TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, - bool only_enabled = true, - const char** matching_category = NULL, - TypeCategoryImpl::FormatCategoryItems* matching_type = NULL) + AnyMatches(ConstString type_name, + TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = nullptr, + TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr) { return m_categories_map.AnyMatches(type_name, items, @@ -226,29 +238,21 @@ public: ShouldPrintAsOneLiner (ValueObject& valobj); void - Changed () - { - ++m_last_revision; - m_format_cache.Clear (); - } + Changed () override; uint32_t - GetCurrentRevision () + GetCurrentRevision () override { return m_last_revision; } - - ~FormatManager () - { - } - + static FormattersMatchVector GetPossibleMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { FormattersMatchVector matches; GetPossibleMatches (valobj, - valobj.GetClangType(), + valobj.GetCompilerType(), lldb_private::eFormatterChoiceCriterionDirectChoice, use_dynamic, matches, @@ -258,12 +262,23 @@ public: true); return matches; } + + static ConstString + GetTypeForCache (ValueObject&, lldb::DynamicValueType); + + LanguageCategory* + GetCategoryForLanguage (lldb::LanguageType lang_type); + + static std::vector + GetCandidateLanguages (lldb::LanguageType lang_type); private: + static std::vector + GetCandidateLanguages (ValueObject& valobj); static void GetPossibleMatches (ValueObject& valobj, - ClangASTType clang_type, + CompilerType compiler_type, uint32_t reason, lldb::DynamicValueType use_dynamic, FormattersMatchVector& entries, @@ -271,40 +286,29 @@ private: bool did_strip_ref, bool did_strip_typedef, bool root_level = false); - + + std::atomic m_last_revision; FormatCache m_format_cache; + Mutex m_language_categories_mutex; + LanguageCategories m_language_categories_map; NamedSummariesMap m_named_summaries_map; - std::atomic m_last_revision; TypeCategoryMap m_categories_map; ConstString m_default_category_name; ConstString m_system_category_name; - ConstString m_gnu_cpp_category_name; - ConstString m_libcxx_category_name; - ConstString m_objc_category_name; - ConstString m_corefoundation_category_name; - ConstString m_coregraphics_category_name; - ConstString m_coreservices_category_name; ConstString m_vectortypes_category_name; - ConstString m_appkit_category_name; - ConstString m_coremedia_category_name; - - HardcodedFormatterFinders m_hardcoded_formats; - HardcodedFormatterFinders m_hardcoded_summaries; - HardcodedFormatterFinders m_hardcoded_synthetics; - HardcodedFormatterFinders m_hardcoded_validators; lldb::TypeFormatImplSP - GetHardcodedFormat (ValueObject&,lldb::DynamicValueType); + GetHardcodedFormat (FormattersMatchData&); lldb::TypeSummaryImplSP - GetHardcodedSummaryFormat (ValueObject&,lldb::DynamicValueType); + GetHardcodedSummaryFormat (FormattersMatchData&); lldb::SyntheticChildrenSP - GetHardcodedSyntheticChildren (ValueObject&,lldb::DynamicValueType); + GetHardcodedSyntheticChildren (FormattersMatchData&); lldb::TypeValidatorImplSP - GetHardcodedValidator (ValueObject&,lldb::DynamicValueType); + GetHardcodedValidator (FormattersMatchData&); TypeCategoryMap& GetCategories () @@ -312,29 +316,20 @@ private: return m_categories_map; } - // WARNING: these are temporary functions that setup formatters - // while a few of these actually should be globally available and setup by LLDB itself - // most would actually belong to the users' lldbinit file or to some other form of configurable - // storage - void - LoadLibStdcppFormatters (); - - void - LoadLibcxxFormatters (); - + // These functions are meant to initialize formatters that are very low-level/global in nature + // and do not naturally belong in any language. The intent is that most formatters go in + // language-specific categories. Eventually, the runtimes should also be allowed to vend their + // own formatters, and then one could put formatters that depend on specific library load events + // in the language runtimes, on an as-needed basis void LoadSystemFormatters (); void - LoadObjCFormatters (); - - void - LoadCoreMediaFormatters (); + LoadVectorFormatters (); - void - LoadHardcodedFormatters (); + friend class FormattersMatchData; }; } // namespace lldb_private -#endif // lldb_FormatManager_h_ +#endif // lldb_FormatManager_h_ diff --git a/include/lldb/DataFormatters/FormattersContainer.h b/include/lldb/DataFormatters/FormattersContainer.h index daf2f24ae3e5..dcd08211f19b 100644 --- a/include/lldb/DataFormatters/FormattersContainer.h +++ b/include/lldb/DataFormatters/FormattersContainer.h @@ -1,4 +1,4 @@ -//===-- FormattersContainer.h ----------------------------------------*- C++ -*-===// +//===-- FormattersContainer.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,53 +12,38 @@ // C Includes // C++ Includes +#include +#include +#include +#include // Other libraries and framework includes -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Type.h" -#include "clang/AST/DeclObjC.h" - // Project includes #include "lldb/lldb-public.h" -#include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/ValueObject.h" - #include "lldb/DataFormatters/FormatClasses.h" #include "lldb/DataFormatters/TypeFormat.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/DataFormatters/TypeValidator.h" - -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTType.h" - -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/TargetList.h" - +#include "lldb/Symbol/CompilerType.h" #include "lldb/Utility/StringLexer.h" namespace lldb_private { -// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization -// class DataVisualization is the high-level front-end of this feature -// clients should refer to that class as the entry-point into the data formatters -// unless they have a good reason to bypass it and prefer to use this file's objects directly class IFormatChangeListener { public: + virtual + ~IFormatChangeListener() = default; + virtual void Changed () = 0; - - virtual - ~IFormatChangeListener () {} - + virtual uint32_t GetCurrentRevision () = 0; - }; // if the user tries to add formatters for, say, "struct Foo" @@ -92,11 +77,10 @@ template class FormatMap { public: - typedef typename ValueType::SharedPointer ValueSP; typedef std::map MapType; typedef typename MapType::iterator MapIterator; - typedef bool(*CallbackType)(void*, KeyType, const ValueSP&); + typedef std::function ForEachCallback; FormatMap(IFormatChangeListener* lst) : m_map(), @@ -155,7 +139,7 @@ public: } void - LoopThrough (CallbackType callback, void* param) + ForEach (ForEachCallback callback) { if (callback) { @@ -164,7 +148,7 @@ public: for (pos = m_map.begin(); pos != end; pos++) { KeyType type = pos->first; - if (!callback(param, type, pos->second)) + if (!callback(type, pos->second)) break; } } @@ -227,7 +211,6 @@ protected: friend class FormattersContainer; friend class FormatManager; - }; template @@ -241,7 +224,7 @@ public: typedef typename MapType::iterator MapIterator; typedef typename MapType::key_type MapKeyType; typedef typename MapType::mapped_type MapValueType; - typedef typename BackEndType::CallbackType CallbackType; + typedef typename BackEndType::ForEachCallback ForEachCallback; typedef typename std::shared_ptr > SharedPointer; friend class TypeCategoryImpl; @@ -256,23 +239,23 @@ public: void Add (const MapKeyType &type, const MapValueType& entry) { - Add_Impl(type, entry, (KeyType*)NULL); + Add_Impl(type, entry, static_cast(nullptr)); } bool Delete (ConstString type) { - return Delete_Impl(type, (KeyType*)NULL); + return Delete_Impl(type, static_cast(nullptr)); } bool Get(ValueObject& valobj, MapValueType& entry, lldb::DynamicValueType use_dynamic, - uint32_t* why = NULL) + uint32_t* why = nullptr) { uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; - ClangASTType ast_type(valobj.GetClangType()); + CompilerType ast_type(valobj.GetCompilerType()); bool ret = Get(valobj, ast_type, entry, use_dynamic, value); if (ret) entry = MapValueType(entry); @@ -286,13 +269,13 @@ public: bool Get (ConstString type, MapValueType& entry) { - return Get_Impl(type, entry, (KeyType*)NULL); + return Get_Impl(type, entry, static_cast(nullptr)); } bool GetExact (ConstString type, MapValueType& entry) { - return GetExact_Impl(type, entry, (KeyType*)NULL); + return GetExact_Impl(type, entry, static_cast(nullptr)); } MapValueType @@ -304,7 +287,7 @@ public: lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex (size_t index) { - return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL); + return GetTypeNameSpecifierAtIndex_Impl(index, static_cast(nullptr)); } void @@ -314,9 +297,9 @@ public: } void - LoopThrough (CallbackType callback, void* param) + ForEach (ForEachCallback callback) { - m_format_map.LoopThrough(callback,param); + m_format_map.ForEach(callback); } uint32_t @@ -377,7 +360,7 @@ protected: bool GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy) { - return Get_Impl(type,entry, (KeyType*)0); + return Get_Impl(type, entry, static_cast(nullptr)); } lldb::TypeNameSpecifierImplSP @@ -395,7 +378,7 @@ protected: GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy) { lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); - if (regex.get() == NULL) + if (regex.get() == nullptr) return lldb::TypeNameSpecifierImplSP(); return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(), true)); @@ -447,7 +430,6 @@ protected: { for (const FormattersMatchCandidate& candidate : candidates) { - // FIXME: could we do the IsMatch() check first? if (Get(candidate.GetTypeName(),entry)) { if (candidate.IsMatch(entry) == false) @@ -469,4 +451,4 @@ protected: } // namespace lldb_private -#endif // lldb_FormattersContainer_h_ +#endif // lldb_FormattersContainer_h_ diff --git a/include/lldb/DataFormatters/FormattersHelpers.h b/include/lldb/DataFormatters/FormattersHelpers.h new file mode 100644 index 000000000000..4627a61e94f1 --- /dev/null +++ b/include/lldb/DataFormatters/FormattersHelpers.h @@ -0,0 +1,279 @@ +//===-- FormattersHelpers.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_FormattersHelpers_h_ +#define lldb_FormattersHelpers_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/DataFormatters/TypeCategory.h" +#include "lldb/DataFormatters/TypeFormat.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +namespace lldb_private { + namespace formatters { + void + AddFormat (TypeCategoryImpl::SharedPointer category_sp, + lldb::Format format, + ConstString type_name, + TypeFormatImpl::Flags flags, + bool regex = false); + + void + AddSummary(TypeCategoryImpl::SharedPointer category_sp, + lldb::TypeSummaryImplSP summary_sp, + ConstString type_name, + bool regex = false); + + void + AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, + const char* string, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex = false); + + void + AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex = false); + +#ifndef LLDB_DISABLE_PYTHON + void + AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp, + CXXFunctionSummaryFormat::Callback funct, + const char* description, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex = false); + + void + AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp, + CXXSyntheticChildren::CreateFrontEndCallback generator, + const char* description, + ConstString type_name, + ScriptedSyntheticChildren::Flags flags, + bool regex = false); + + void + AddFilter (TypeCategoryImpl::SharedPointer category_sp, + std::vector children, + const char* description, + ConstString type_name, + ScriptedSyntheticChildren::Flags flags, + bool regex = false); +#endif + + StackFrame* + GetViableFrame (ExecutionContext exe_ctx); + + bool + ExtractValueFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + uint64_t &value); + + bool + ExtractSummaryFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + Stream &stream, + lldb::LanguageType lang_type); + + lldb::ValueObjectSP + CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + uint64_t index); + + lldb::ValueObjectSP + CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + const char* key); + + size_t + ExtractIndexFromString (const char* item_name); + + lldb::addr_t + GetArrayAddressOrPointerValue (ValueObject& valobj); + + time_t + GetOSXEpoch (); + + struct InferiorSizedWord { + + InferiorSizedWord(const InferiorSizedWord& word) : ptr_size(word.ptr_size) + { + if (ptr_size == 4) + thirty_two = word.thirty_two; + else + sixty_four = word.sixty_four; + } + + InferiorSizedWord + operator = (const InferiorSizedWord& word) + { + ptr_size = word.ptr_size; + if (ptr_size == 4) + thirty_two = word.thirty_two; + else + sixty_four = word.sixty_four; + return *this; + } + + InferiorSizedWord(uint64_t val, Process& process) : ptr_size(process.GetAddressByteSize()) + { + if (ptr_size == 4) + thirty_two = (uint32_t)val; + else if (ptr_size == 8) + sixty_four = val; + else + assert (false && "new pointer size is unknown"); + } + + bool + IsNegative () const + { + if (ptr_size == 4) + return ((int32_t)thirty_two) < 0; + else + return ((int64_t)sixty_four) < 0; + } + + bool + IsZero () const + { + if (ptr_size == 4) + return thirty_two == 0; + else + return sixty_four == 0; + } + + static InferiorSizedWord + GetMaximum (Process& process) + { + if (process.GetAddressByteSize() == 4) + return InferiorSizedWord(UINT32_MAX,4); + else + return InferiorSizedWord(UINT64_MAX,8); + } + + InferiorSizedWord + operator >> (int rhs) const + { + if (ptr_size == 4) + return InferiorSizedWord(thirty_two >> rhs,4); + return InferiorSizedWord(sixty_four>>rhs,8); + } + + InferiorSizedWord + operator << (int rhs) const + { + if (ptr_size == 4) + return InferiorSizedWord(thirty_two << rhs,4); + return InferiorSizedWord(sixty_four << rhs,8); + } + + InferiorSizedWord + operator & (const InferiorSizedWord& word) const + { + if (ptr_size != word.ptr_size) + return InferiorSizedWord(0,ptr_size); + if (ptr_size == 4) + return InferiorSizedWord(thirty_two & word.thirty_two,4); + return InferiorSizedWord(sixty_four & word.sixty_four,8); + } + + InferiorSizedWord + operator & (int x) const + { + if (ptr_size == 4) + return InferiorSizedWord(thirty_two & x,4); + return InferiorSizedWord(sixty_four & x,8); + } + + size_t + GetBitSize () const + { + return ptr_size << 3; + } + + size_t + GetByteSize () const + { + return ptr_size; + } + + uint64_t + GetValue () const + { + if (ptr_size == 4) + return (uint64_t)thirty_two; + return sixty_four; + } + + InferiorSizedWord + SignExtend () const + { + if (ptr_size == 4) + return InferiorSizedWord ((int32_t)thirty_two,4); + return InferiorSizedWord((int64_t)sixty_four,8); + } + + uint8_t* + CopyToBuffer (uint8_t* buffer) const + { + if (ptr_size == 4) + { + memcpy(buffer, &thirty_two, 4); + return buffer + 4; + } + else + { + memcpy(buffer, &sixty_four, 8); + return buffer + 8; + } + } + + DataExtractor + GetAsData (lldb::ByteOrder byte_order = lldb::eByteOrderInvalid) const + { + if (ptr_size == 4) + return DataExtractor(&thirty_two, 4, byte_order, 4); + else + return DataExtractor(&sixty_four, 8, byte_order, 8); + } + + private: + + InferiorSizedWord(uint64_t val, size_t psz) : ptr_size(psz) + { + if (ptr_size == 4) + thirty_two = (uint32_t)val; + else + sixty_four = val; + } + + size_t ptr_size; + union { + uint32_t thirty_two; + uint64_t sixty_four; + }; + }; + } // namespace formatters +} // namespace lldb_private + +#endif // lldb_FormattersHelpers_h_ diff --git a/include/lldb/DataFormatters/LanguageCategory.h b/include/lldb/DataFormatters/LanguageCategory.h new file mode 100644 index 000000000000..a7040099f213 --- /dev/null +++ b/include/lldb/DataFormatters/LanguageCategory.h @@ -0,0 +1,99 @@ +//===-- LanguageCategory.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_LanguageCategory_h_ +#define lldb_LanguageCategory_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/DataFormatters/FormatCache.h" +#include "lldb/DataFormatters/FormatClasses.h" + +#include + +namespace lldb_private { + +class LanguageCategory +{ +public: + typedef std::unique_ptr UniquePointer; + + LanguageCategory (lldb::LanguageType lang_type); + + bool + Get (FormattersMatchData& match_data, + lldb::TypeFormatImplSP& format_sp); + + bool + Get (FormattersMatchData& match_data, + lldb::TypeSummaryImplSP& format_sp); + + bool + Get (FormattersMatchData& match_data, + lldb::SyntheticChildrenSP& format_sp); + + bool + Get (FormattersMatchData& match_data, + lldb::TypeValidatorImplSP& format_sp); + + bool + GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeFormatImplSP& format_sp); + + bool + GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeSummaryImplSP& format_sp); + + bool + GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::SyntheticChildrenSP& format_sp); + + bool + GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeValidatorImplSP& format_sp); + + lldb::TypeCategoryImplSP + GetCategory () const; + + FormatCache& + GetFormatCache (); + + void + Enable (); + + void + Disable (); + + bool + IsEnabled (); + +private: + lldb::TypeCategoryImplSP m_category_sp; + + HardcodedFormatters::HardcodedFormatFinder m_hardcoded_formats; + HardcodedFormatters::HardcodedSummaryFinder m_hardcoded_summaries; + HardcodedFormatters::HardcodedSyntheticFinder m_hardcoded_synthetics; + HardcodedFormatters::HardcodedValidatorFinder m_hardcoded_validators; + + lldb_private::FormatCache m_format_cache; + + bool m_enabled; +}; + +} // namespace lldb_private + +#endif // lldb_LanguageCategory_h_ diff --git a/include/lldb/DataFormatters/StringPrinter.h b/include/lldb/DataFormatters/StringPrinter.h index 48e27ace5d92..a849c4e01109 100644 --- a/include/lldb/DataFormatters/StringPrinter.h +++ b/include/lldb/DataFormatters/StringPrinter.h @@ -10,6 +10,13 @@ #ifndef liblldb_StringPrinter_h_ #define liblldb_StringPrinter_h_ +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-forward.h" #include "lldb/Core/DataExtractor.h" @@ -17,273 +24,505 @@ namespace lldb_private { namespace formatters { - - enum class StringElementType { - ASCII, - UTF8, - UTF16, - UTF32 - }; - - class ReadStringAndDumpToStreamOptions + class StringPrinter { public: - - ReadStringAndDumpToStreamOptions () : - m_location(0), - m_process_sp(), - m_stream(NULL), - m_prefix_token(0), - m_quote('"'), - m_source_size(0), - m_needs_zero_termination(true), - m_escape_non_printables(true), - m_ignore_max_length(false) - { - } - - ReadStringAndDumpToStreamOptions (ValueObject& valobj); - - ReadStringAndDumpToStreamOptions& - SetLocation (uint64_t l) - { - m_location = l; - return *this; - } - - uint64_t - GetLocation () const - { - return m_location; - } - - ReadStringAndDumpToStreamOptions& - SetProcessSP (lldb::ProcessSP p) - { - m_process_sp = p; - return *this; - } - - lldb::ProcessSP - GetProcessSP () const - { - return m_process_sp; - } - - ReadStringAndDumpToStreamOptions& - SetStream (Stream* s) - { - m_stream = s; - return *this; - } - - Stream* - GetStream () const - { - return m_stream; - } - - ReadStringAndDumpToStreamOptions& - SetPrefixToken (char p) - { - m_prefix_token = p; - return *this; - } - - char - GetPrefixToken () const - { - return m_prefix_token; - } - - ReadStringAndDumpToStreamOptions& - SetQuote (char q) - { - m_quote = q; - return *this; - } - - char - GetQuote () const - { - return m_quote; - } - - ReadStringAndDumpToStreamOptions& - SetSourceSize (uint32_t s) - { - m_source_size = s; - return *this; - } - - uint32_t - GetSourceSize () const - { - return m_source_size; - } - - ReadStringAndDumpToStreamOptions& - SetNeedsZeroTermination (bool z) - { - m_needs_zero_termination = z; - return *this; - } - - bool - GetNeedsZeroTermination () const - { - return m_needs_zero_termination; - } - - ReadStringAndDumpToStreamOptions& - SetEscapeNonPrintables (bool e) - { - m_escape_non_printables = e; - return *this; - } - - bool - GetEscapeNonPrintables () const - { - return m_escape_non_printables; - } - - ReadStringAndDumpToStreamOptions& - SetIgnoreMaxLength (bool e) - { - m_ignore_max_length = e; - return *this; - } - - bool - GetIgnoreMaxLength () const - { - return m_ignore_max_length; - } - - private: - uint64_t m_location; - lldb::ProcessSP m_process_sp; - Stream* m_stream; - char m_prefix_token; - char m_quote; - uint32_t m_source_size; - bool m_needs_zero_termination; - bool m_escape_non_printables; - bool m_ignore_max_length; - }; - - class ReadBufferAndDumpToStreamOptions - { - public: - - ReadBufferAndDumpToStreamOptions () : - m_data(), - m_stream(NULL), - m_prefix_token(0), - m_quote('"'), - m_source_size(0), - m_escape_non_printables(true) - { - } - - ReadBufferAndDumpToStreamOptions (ValueObject& valobj); - - ReadBufferAndDumpToStreamOptions& - SetData (DataExtractor d) - { - m_data = d; - return *this; - } - - lldb_private::DataExtractor - GetData () const - { - return m_data; - } - - ReadBufferAndDumpToStreamOptions& - SetStream (Stream* s) - { - m_stream = s; - return *this; - } - - Stream* - GetStream () const - { - return m_stream; - } - - ReadBufferAndDumpToStreamOptions& - SetPrefixToken (char p) - { - m_prefix_token = p; - return *this; - } - - char - GetPrefixToken () const - { - return m_prefix_token; - } - - ReadBufferAndDumpToStreamOptions& - SetQuote (char q) - { - m_quote = q; - return *this; - } - - char - GetQuote () const - { - return m_quote; - } - - ReadBufferAndDumpToStreamOptions& - SetSourceSize (uint32_t s) - { - m_source_size = s; - return *this; - } - - uint32_t - GetSourceSize () const - { - return m_source_size; - } - - ReadBufferAndDumpToStreamOptions& - SetEscapeNonPrintables (bool e) - { - m_escape_non_printables = e; - return *this; - } - - bool - GetEscapeNonPrintables () const - { - return m_escape_non_printables; - } - - private: - DataExtractor m_data; - Stream* m_stream; - char m_prefix_token; - char m_quote; - uint32_t m_source_size; - bool m_escape_non_printables; + enum class StringElementType + { + ASCII, + UTF8, + UTF16, + UTF32 + }; + + enum class GetPrintableElementType + { + ASCII, + UTF8 + }; + + class ReadStringAndDumpToStreamOptions + { + public: + ReadStringAndDumpToStreamOptions () : + m_location(0), + m_process_sp(), + m_stream(nullptr), + m_prefix_token(), + m_suffix_token(), + m_quote('"'), + m_source_size(0), + m_needs_zero_termination(true), + m_escape_non_printables(true), + m_ignore_max_length(false), + m_zero_is_terminator(true), + m_language_type(lldb::eLanguageTypeUnknown) + { + } + + ReadStringAndDumpToStreamOptions (ValueObject& valobj); + + ReadStringAndDumpToStreamOptions& + SetLocation (uint64_t l) + { + m_location = l; + return *this; + } + + uint64_t + GetLocation () const + { + return m_location; + } + + ReadStringAndDumpToStreamOptions& + SetProcessSP (lldb::ProcessSP p) + { + m_process_sp = p; + return *this; + } + + lldb::ProcessSP + GetProcessSP () const + { + return m_process_sp; + } + + ReadStringAndDumpToStreamOptions& + SetStream (Stream* s) + { + m_stream = s; + return *this; + } + + Stream* + GetStream () const + { + return m_stream; + } + + ReadStringAndDumpToStreamOptions& + SetPrefixToken (const std::string& p) + { + m_prefix_token = p; + return *this; + } + + ReadStringAndDumpToStreamOptions& + SetPrefixToken (std::nullptr_t) + { + m_prefix_token.clear(); + return *this; + } + + const char* + GetPrefixToken () const + { + return m_prefix_token.c_str(); + } + + ReadStringAndDumpToStreamOptions& + SetSuffixToken (const std::string& p) + { + m_suffix_token = p; + return *this; + } + + ReadStringAndDumpToStreamOptions& + SetSuffixToken (std::nullptr_t) + { + m_suffix_token.clear(); + return *this; + } + + const char* + GetSuffixToken () const + { + return m_suffix_token.c_str(); + } + + ReadStringAndDumpToStreamOptions& + SetQuote (char q) + { + m_quote = q; + return *this; + } + + char + GetQuote () const + { + return m_quote; + } + + ReadStringAndDumpToStreamOptions& + SetSourceSize (uint32_t s) + { + m_source_size = s; + return *this; + } + + uint32_t + GetSourceSize () const + { + return m_source_size; + } + + ReadStringAndDumpToStreamOptions& + SetNeedsZeroTermination (bool z) + { + m_needs_zero_termination = z; + return *this; + } + + bool + GetNeedsZeroTermination () const + { + return m_needs_zero_termination; + } + + ReadStringAndDumpToStreamOptions& + SetBinaryZeroIsTerminator (bool e) + { + m_zero_is_terminator = e; + return *this; + } + + bool + GetBinaryZeroIsTerminator () const + { + return m_zero_is_terminator; + } + + ReadStringAndDumpToStreamOptions& + SetEscapeNonPrintables (bool e) + { + m_escape_non_printables = e; + return *this; + } + + bool + GetEscapeNonPrintables () const + { + return m_escape_non_printables; + } + + ReadStringAndDumpToStreamOptions& + SetIgnoreMaxLength (bool e) + { + m_ignore_max_length = e; + return *this; + } + + bool + GetIgnoreMaxLength () const + { + return m_ignore_max_length; + } + + ReadStringAndDumpToStreamOptions& + SetLanguage (lldb::LanguageType l) + { + m_language_type = l; + return *this; + } + + lldb::LanguageType + GetLanguage () const + + { + return m_language_type; + } + + private: + uint64_t m_location; + lldb::ProcessSP m_process_sp; + Stream* m_stream; + std::string m_prefix_token; + std::string m_suffix_token; + char m_quote; + uint32_t m_source_size; + bool m_needs_zero_termination; + bool m_escape_non_printables; + bool m_ignore_max_length; + bool m_zero_is_terminator; + lldb::LanguageType m_language_type; + }; + + class ReadBufferAndDumpToStreamOptions + { + public: + ReadBufferAndDumpToStreamOptions () : + m_data(), + m_stream(nullptr), + m_prefix_token(), + m_suffix_token(), + m_quote('"'), + m_source_size(0), + m_escape_non_printables(true), + m_zero_is_terminator(true), + m_is_truncated(false), + m_language_type(lldb::eLanguageTypeUnknown) + { + } + + ReadBufferAndDumpToStreamOptions (ValueObject& valobj); + + ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options); + + ReadBufferAndDumpToStreamOptions& + SetData (DataExtractor d) + { + m_data = d; + return *this; + } + + lldb_private::DataExtractor + GetData () const + { + return m_data; + } + + ReadBufferAndDumpToStreamOptions& + SetStream (Stream* s) + { + m_stream = s; + return *this; + } + + Stream* + GetStream () const + { + return m_stream; + } + + ReadBufferAndDumpToStreamOptions& + SetPrefixToken (const std::string& p) + { + m_prefix_token = p; + return *this; + } + + ReadBufferAndDumpToStreamOptions& + SetPrefixToken (std::nullptr_t) + { + m_prefix_token.clear(); + return *this; + } + + const char* + GetPrefixToken () const + { + return m_prefix_token.c_str(); + } + + ReadBufferAndDumpToStreamOptions& + SetSuffixToken (const std::string& p) + { + m_suffix_token = p; + return *this; + } + + ReadBufferAndDumpToStreamOptions& + SetSuffixToken (std::nullptr_t) + { + m_suffix_token.clear(); + return *this; + } + + const char* + GetSuffixToken () const + { + return m_suffix_token.c_str(); + } + + ReadBufferAndDumpToStreamOptions& + SetQuote (char q) + { + m_quote = q; + return *this; + } + + char + GetQuote () const + { + return m_quote; + } + + ReadBufferAndDumpToStreamOptions& + SetSourceSize (uint32_t s) + { + m_source_size = s; + return *this; + } + + uint32_t + GetSourceSize () const + { + return m_source_size; + } + + ReadBufferAndDumpToStreamOptions& + SetEscapeNonPrintables (bool e) + { + m_escape_non_printables = e; + return *this; + } + + bool + GetEscapeNonPrintables () const + { + return m_escape_non_printables; + } + + ReadBufferAndDumpToStreamOptions& + SetBinaryZeroIsTerminator (bool e) + { + m_zero_is_terminator = e; + return *this; + } + + bool + GetBinaryZeroIsTerminator () const + { + return m_zero_is_terminator; + } + + ReadBufferAndDumpToStreamOptions& + SetIsTruncated (bool t) + { + m_is_truncated = t; + return *this; + } + + bool + GetIsTruncated () const + { + return m_is_truncated; + } + + ReadBufferAndDumpToStreamOptions& + SetLanguage (lldb::LanguageType l) + { + m_language_type = l; + return *this; + } + + lldb::LanguageType + GetLanguage () const + + { + return m_language_type; + } + + private: + DataExtractor m_data; + Stream* m_stream; + std::string m_prefix_token; + std::string m_suffix_token; + char m_quote; + uint32_t m_source_size; + bool m_escape_non_printables; + bool m_zero_is_terminator; + bool m_is_truncated; + lldb::LanguageType m_language_type; + }; + + // I can't use a std::unique_ptr for this because the Deleter is a template argument there + // and I want the same type to represent both pointers I want to free and pointers I don't need + // to free - which is what this class essentially is + // It's very specialized to the needs of this file, and not suggested for general use + template + struct StringPrinterBufferPointer + { + public: + typedef std::function Deleter; + + StringPrinterBufferPointer (std::nullptr_t ptr) : + m_data(nullptr), + m_size(0), + m_deleter() + {} + + StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) : + m_data(bytes), + m_size(size), + m_deleter(deleter) + {} + + StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) : + m_data(reinterpret_cast(bytes)), + m_size(size), + m_deleter(deleter) + {} + + StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) : + m_data(rhs.m_data), + m_size(rhs.m_size), + m_deleter(rhs.m_deleter) + { + rhs.m_data = nullptr; + } + + StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) : + m_data(rhs.m_data), + m_size(rhs.m_size), + m_deleter(rhs.m_deleter) + { + rhs.m_data = nullptr; // this is why m_data has to be mutable + } + + ~StringPrinterBufferPointer() + { + if (m_data && m_deleter) + m_deleter(m_data); + m_data = nullptr; + } + + const T* + GetBytes () const + { + return m_data; + } + + const S + GetSize () const + { + return m_size; + } + + StringPrinterBufferPointer& + operator = (const StringPrinterBufferPointer& rhs) + { + if (m_data && m_deleter) + m_deleter(m_data); + m_data = rhs.m_data; + m_size = rhs.m_size; + m_deleter = rhs.m_deleter; + rhs.m_data = nullptr; + return *this; + } + + private: + mutable const T* m_data; + size_t m_size; + Deleter m_deleter; + }; + + typedef std::function(uint8_t*, uint8_t*, uint8_t*&)> EscapingHelper; + typedef std::function EscapingHelperGenerator; + + static EscapingHelper + GetDefaultEscapingHelper (GetPrintableElementType elem_type); + + template + static bool + ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options); + + template + static bool + ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options); }; - template - bool - ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options); - - template - bool - ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options); - } // namespace formatters } // namespace lldb_private diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h index e32efa420a55..075d31d1cf6f 100644 --- a/include/lldb/DataFormatters/TypeCategory.h +++ b/include/lldb/DataFormatters/TypeCategory.h @@ -1,4 +1,4 @@ -//===-- TypeCategory.h -------------------------------------------*- C++ -*-===// +//===-- TypeCategory.h ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,10 @@ // C Includes // C++ Includes +#include +#include +#include +#include // Other libraries and framework includes // Project includes @@ -38,6 +42,9 @@ namespace lldb_private { typedef typename ExactMatchContainer::SharedPointer ExactMatchContainerSP; typedef typename RegexMatchContainer::SharedPointer RegexMatchContainerSP; + typedef typename ExactMatchContainer::ForEachCallback ExactMatchForEachCallback; + typedef typename RegexMatchContainer::ForEachCallback RegexMatchForEachCallback; + FormatterContainerPair (const char* exact_name, const char* regex_name, IFormatChangeListener* clist) : @@ -60,6 +67,12 @@ namespace lldb_private { return m_regex_sp; } + uint32_t + GetCount () + { + return GetExactMatch()->GetCount() + GetRegexMatch()->GetCount(); + } + private: ExactMatchContainerSP m_exact_sp; RegexMatchContainerSP m_regex_sp; @@ -74,11 +87,10 @@ namespace lldb_private { typedef FormatterContainerPair ValidatorContainer; #ifndef LLDB_DISABLE_PYTHON - typedef FormatterContainerPair SynthContainer; -#endif // #ifndef LLDB_DISABLE_PYTHON + typedef FormatterContainerPair SynthContainer; +#endif // LLDB_DISABLE_PYTHON public: - typedef uint16_t FormatCategoryItems; static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; @@ -93,13 +105,195 @@ namespace lldb_private { #ifndef LLDB_DISABLE_PYTHON typedef SynthContainer::ExactMatchContainerSP SynthContainerSP; typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP; -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif // LLDB_DISABLE_PYTHON typedef ValidatorContainer::ExactMatchContainerSP ValidatorContainerSP; typedef ValidatorContainer::RegexMatchContainerSP RegexValidatorContainerSP; + template + class ForEachCallbacks + { + public: + ForEachCallbacks () = default; + ~ForEachCallbacks () = default; + + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetExact (FormatContainer::ExactMatchForEachCallback callback) + { + m_format_exact = callback; + return *this; + } + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetWithRegex (FormatContainer::RegexMatchForEachCallback callback) + { + m_format_regex = callback; + return *this; + } + + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetExact (SummaryContainer::ExactMatchForEachCallback callback) + { + m_summary_exact = callback; + return *this; + } + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetWithRegex (SummaryContainer::RegexMatchForEachCallback callback) + { + m_summary_regex = callback; + return *this; + } + + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetExact (FilterContainer::ExactMatchForEachCallback callback) + { + m_filter_exact = callback; + return *this; + } + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetWithRegex (FilterContainer::RegexMatchForEachCallback callback) + { + m_filter_regex = callback; + return *this; + } + +#ifndef LLDB_DISABLE_PYTHON + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetExact (SynthContainer::ExactMatchForEachCallback callback) + { + m_synth_exact = callback; + return *this; + } + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetWithRegex (SynthContainer::RegexMatchForEachCallback callback) + { + m_synth_regex = callback; + return *this; + } +#endif // LLDB_DISABLE_PYTHON + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetExact (ValidatorContainer::ExactMatchForEachCallback callback) + { + m_validator_exact = callback; + return *this; + } + template + typename std::enable_if::value, ForEachCallbacks&>::type + SetWithRegex (ValidatorContainer::RegexMatchForEachCallback callback) + { + m_validator_regex = callback; + return *this; + } + + FormatContainer::ExactMatchForEachCallback + GetFormatExactCallback () const + { + return m_format_exact; + } + FormatContainer::RegexMatchForEachCallback + GetFormatRegexCallback () const + { + return m_format_regex; + } + + SummaryContainer::ExactMatchForEachCallback + GetSummaryExactCallback () const + { + return m_summary_exact; + } + SummaryContainer::RegexMatchForEachCallback + GetSummaryRegexCallback () const + { + return m_summary_regex; + } + + FilterContainer::ExactMatchForEachCallback + GetFilterExactCallback () const + { + return m_filter_exact; + } + FilterContainer::RegexMatchForEachCallback + GetFilterRegexCallback () const + { + return m_filter_regex; + } + +#ifndef LLDB_DISABLE_PYTHON + SynthContainer::ExactMatchForEachCallback + GetSynthExactCallback () const + { + return m_synth_exact; + } + SynthContainer::RegexMatchForEachCallback + GetSynthRegexCallback () const + { + return m_synth_regex; + } +#endif // LLDB_DISABLE_PYTHON + + ValidatorContainer::ExactMatchForEachCallback + GetValidatorExactCallback () const + { + return m_validator_exact; + } + ValidatorContainer::RegexMatchForEachCallback + GetValidatorRegexCallback () const + { + return m_validator_regex; + } + + private: + FormatContainer::ExactMatchForEachCallback m_format_exact; + FormatContainer::RegexMatchForEachCallback m_format_regex; + + SummaryContainer::ExactMatchForEachCallback m_summary_exact; + SummaryContainer::RegexMatchForEachCallback m_summary_regex; + + FilterContainer::ExactMatchForEachCallback m_filter_exact; + FilterContainer::RegexMatchForEachCallback m_filter_regex; + +#ifndef LLDB_DISABLE_PYTHON + SynthContainer::ExactMatchForEachCallback m_synth_exact; + SynthContainer::RegexMatchForEachCallback m_synth_regex; +#endif // LLDB_DISABLE_PYTHON + + ValidatorContainer::ExactMatchForEachCallback m_validator_exact; + ValidatorContainer::RegexMatchForEachCallback m_validator_regex; + }; + TypeCategoryImpl (IFormatChangeListener* clist, - ConstString name); + ConstString name, + std::initializer_list langs = {}); + + template + void + ForEach (const ForEachCallbacks &foreach) + { + GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback()); + GetRegexTypeFormatsContainer()->ForEach(foreach.GetFormatRegexCallback()); + + GetTypeSummariesContainer()->ForEach(foreach.GetSummaryExactCallback()); + GetRegexTypeSummariesContainer()->ForEach(foreach.GetSummaryRegexCallback()); + + GetTypeFiltersContainer()->ForEach(foreach.GetFilterExactCallback()); + GetRegexTypeFiltersContainer()->ForEach(foreach.GetFilterRegexCallback()); + +#ifndef LLDB_DISABLE_PYTHON + GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback()); + GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback()); +#endif // LLDB_DISABLE_PYTHON + + GetTypeValidatorsContainer()->ForEach(foreach.GetValidatorExactCallback()); + GetRegexTypeValidatorsContainer()->ForEach(foreach.GetValidatorRegexCallback()); + } FormatContainerSP GetTypeFormatsContainer () @@ -113,6 +307,12 @@ namespace lldb_private { return m_format_cont.GetRegexMatch(); } + FormatContainer& + GetFormatContainer () + { + return m_format_cont; + } + SummaryContainerSP GetTypeSummariesContainer () { @@ -125,6 +325,12 @@ namespace lldb_private { return m_summary_cont.GetRegexMatch(); } + SummaryContainer& + GetSummaryContainer () + { + return m_summary_cont; + } + FilterContainerSP GetTypeFiltersContainer () { @@ -136,6 +342,12 @@ namespace lldb_private { { return m_filter_cont.GetRegexMatch(); } + + FilterContainer& + GetFilterContainer () + { + return m_filter_cont; + } FormatContainer::MapValueType GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp); @@ -185,12 +397,18 @@ namespace lldb_private { return m_synth_cont.GetRegexMatch(); } + SynthContainer& + GetSyntheticsContainer () + { + return m_synth_cont; + } + SynthContainer::MapValueType GetSyntheticAtIndex (size_t index); lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForSyntheticAtIndex (size_t index); -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif // LLDB_DISABLE_PYTHON ValidatorContainerSP GetTypeValidatorsContainer () @@ -226,28 +444,28 @@ namespace lldb_private { } bool - Get (ValueObject& valobj, - const FormattersMatchVector& candidates, - lldb::TypeFormatImplSP& entry, - uint32_t* reason = NULL); + Get(ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::TypeFormatImplSP& entry, + uint32_t* reason = nullptr); bool - Get (ValueObject& valobj, - const FormattersMatchVector& candidates, - lldb::TypeSummaryImplSP& entry, - uint32_t* reason = NULL); + Get(ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::TypeSummaryImplSP& entry, + uint32_t* reason = nullptr); bool - Get (ValueObject& valobj, - const FormattersMatchVector& candidates, - lldb::SyntheticChildrenSP& entry, - uint32_t* reason = NULL); + Get(ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::SyntheticChildrenSP& entry, + uint32_t* reason = nullptr); bool - Get (ValueObject& valobj, - const FormattersMatchVector& candidates, - lldb::TypeValidatorImplSP& entry, - uint32_t* reason = NULL); + Get(ValueObject& valobj, + const FormattersMatchVector& candidates, + lldb::TypeValidatorImplSP& entry, + uint32_t* reason = nullptr); void Clear (FormatCategoryItems items = ALL_ITEM_TYPES); @@ -264,13 +482,28 @@ namespace lldb_private { { return m_name.GetCString(); } + + size_t + GetNumLanguages (); + + lldb::LanguageType + GetLanguageAtIndex (size_t idx); + + void + AddLanguage (lldb::LanguageType lang); bool - AnyMatches (ConstString type_name, - FormatCategoryItems items = ALL_ITEM_TYPES, - bool only_enabled = true, - const char** matching_category = NULL, - FormatCategoryItems* matching_type = NULL); + HasLanguage (lldb::LanguageType lang); + + std::string + GetDescription (); + + bool + AnyMatches(ConstString type_name, + FormatCategoryItems items = ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = nullptr, + FormatCategoryItems* matching_type = nullptr); typedef std::shared_ptr SharedPointer; @@ -280,7 +513,7 @@ namespace lldb_private { FilterContainer m_filter_cont; #ifndef LLDB_DISABLE_PYTHON SynthContainer m_synth_cont; -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif // LLDB_DISABLE_PYTHON ValidatorContainer m_validator_cont; bool m_enabled; @@ -291,6 +524,8 @@ namespace lldb_private { ConstString m_name; + std::vector m_languages; + uint32_t m_enabled_position; void @@ -302,6 +537,9 @@ namespace lldb_private { Enable(false, UINT32_MAX); } + bool + IsApplicable (ValueObject& valobj); + uint32_t GetLastEnabledPosition () { @@ -314,6 +552,8 @@ namespace lldb_private { m_enabled_position = p; } + friend class FormatManager; + friend class LanguageCategory; friend class TypeCategoryMap; friend class FormattersContainer; @@ -328,7 +568,7 @@ namespace lldb_private { #ifndef LLDB_DISABLE_PYTHON friend class FormattersContainer; friend class FormattersContainer; -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif // LLDB_DISABLE_PYTHON friend class FormattersContainer; friend class FormattersContainer; @@ -336,4 +576,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // lldb_TypeCategory_h_ +#endif // lldb_TypeCategory_h_ diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h index 41b170d5335e..8afeaf87cec5 100644 --- a/include/lldb/DataFormatters/TypeCategoryMap.h +++ b/include/lldb/DataFormatters/TypeCategoryMap.h @@ -1,4 +1,4 @@ -//===-- TypeCategoryMap.h ----------------------------------------*- C++ -*-===// +//===-- TypeCategoryMap.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,9 @@ // C Includes // C++ Includes +#include +#include +#include // Other libraries and framework includes // Project includes @@ -34,7 +37,8 @@ namespace lldb_private { public: typedef std::map MapType; typedef MapType::iterator MapIterator; - typedef bool(*CallbackType)(void*, const ValueSP&); + typedef std::function ForEachCallback; + typedef uint32_t Position; static const Position First = 0; @@ -82,17 +86,17 @@ namespace lldb_private { ValueSP& entry); void - LoopThrough (CallbackType callback, void* param); + ForEach (ForEachCallback callback); lldb::TypeCategoryImplSP GetAtIndex (uint32_t); bool - AnyMatches (ConstString type_name, - TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, - bool only_enabled = true, - const char** matching_category = NULL, - TypeCategoryImpl::FormatCategoryItems* matching_type = NULL); + AnyMatches(ConstString type_name, + TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = nullptr, + TypeCategoryImpl::FormatCategoryItems* matching_type = nullptr); uint32_t GetCount () @@ -101,25 +105,20 @@ namespace lldb_private { } lldb::TypeFormatImplSP - GetFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic); + GetFormat (FormattersMatchData& match_data); lldb::TypeSummaryImplSP - GetSummaryFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic); + GetSummaryFormat (FormattersMatchData& match_data); #ifndef LLDB_DISABLE_PYTHON lldb::SyntheticChildrenSP - GetSyntheticChildren (ValueObject& valobj, - lldb::DynamicValueType use_dynamic); + GetSyntheticChildren (FormattersMatchData& match_data); #endif - lldb::TypeValidatorImplSP - GetValidator (ValueObject& valobj, - lldb::DynamicValueType use_dynamic); + lldb::TypeValidatorImplSP + GetValidator(FormattersMatchData& match_data); private: - class delete_matching_categories { lldb::TypeCategoryImplSP ptr; @@ -159,4 +158,4 @@ namespace lldb_private { }; } // namespace lldb_private -#endif // lldb_TypeCategoryMap_h_ +#endif // lldb_TypeCategoryMap_h_ diff --git a/include/lldb/DataFormatters/TypeFormat.h b/include/lldb/DataFormatters/TypeFormat.h index 8aa7c60b4938..4ed28b692061 100644 --- a/include/lldb/DataFormatters/TypeFormat.h +++ b/include/lldb/DataFormatters/TypeFormat.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes +#include #include #include @@ -150,7 +151,6 @@ namespace lldb_private { TypeFormatImpl (const Flags& flags = Flags()); typedef std::shared_ptr SharedPointer; - typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeFormatImplSP&); virtual ~TypeFormatImpl (); @@ -159,16 +159,19 @@ namespace lldb_private { { return m_flags.GetCascades(); } + bool SkipsPointers () const { return m_flags.GetSkipPointers(); } + bool SkipsReferences () const { return m_flags.GetSkipReferences(); } + bool NonCacheable () const { @@ -255,9 +258,8 @@ namespace lldb_private { const TypeFormatImpl::Flags& flags = Flags()); typedef std::shared_ptr SharedPointer; - typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_Format::SharedPointer&); - virtual ~TypeFormatImpl_Format (); + ~TypeFormatImpl_Format() override; lldb::Format GetFormat () const @@ -271,18 +273,18 @@ namespace lldb_private { m_format = fmt; } - virtual TypeFormatImpl::Type - GetType () + TypeFormatImpl::Type + GetType() override { return TypeFormatImpl::Type::eTypeFormat; } - virtual bool - FormatObject (ValueObject *valobj, - std::string& dest) const; + bool + FormatObject(ValueObject *valobj, + std::string& dest) const override; - virtual std::string - GetDescription(); + std::string + GetDescription() override; protected: lldb::Format m_format; @@ -298,9 +300,8 @@ namespace lldb_private { const TypeFormatImpl::Flags& flags = Flags()); typedef std::shared_ptr SharedPointer; - typedef bool(*ValueCallback)(void*, ConstString, const TypeFormatImpl_EnumType::SharedPointer&); - ~TypeFormatImpl_EnumType (); + ~TypeFormatImpl_EnumType() override; ConstString GetTypeName () @@ -314,26 +315,26 @@ namespace lldb_private { m_enum_type = enum_type; } - virtual TypeFormatImpl::Type - GetType () + TypeFormatImpl::Type + GetType() override { return TypeFormatImpl::Type::eTypeEnum; } - virtual bool - FormatObject (ValueObject *valobj, - std::string& dest) const; + bool + FormatObject(ValueObject *valobj, + std::string& dest) const override; - virtual std::string - GetDescription(); + std::string + GetDescription() override; protected: ConstString m_enum_type; - mutable std::unordered_map m_types; + mutable std::unordered_map m_types; private: DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl_EnumType); }; } // namespace lldb_private -#endif // lldb_TypeFormat_h_ +#endif // lldb_TypeFormat_h_ diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h index c2838eac27f1..e5bf4ecadfdf 100644 --- a/include/lldb/DataFormatters/TypeSummary.h +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -1,4 +1,4 @@ -//===-- TypeSummary.h --------------------------------------------*- C++ -*-===// +//===-- TypeSummary.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,11 +14,11 @@ #include // C++ Includes +#include +#include #include -#include // Other libraries and framework includes - // Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" @@ -26,8 +26,6 @@ #include "lldb/Core/Error.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/StructuredData.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Symbol/Type.h" namespace lldb_private { class TypeSummaryOptions @@ -36,6 +34,8 @@ namespace lldb_private { TypeSummaryOptions (); TypeSummaryOptions (const TypeSummaryOptions& rhs); + ~TypeSummaryOptions() = default; + TypeSummaryOptions& operator = (const TypeSummaryOptions& rhs); @@ -50,8 +50,7 @@ namespace lldb_private { TypeSummaryOptions& SetCapping (lldb::TypeSummaryCapping); - - ~TypeSummaryOptions() = default; + private: lldb::LanguageType m_lang; lldb::TypeSummaryCapping m_capping; @@ -60,10 +59,26 @@ namespace lldb_private { class TypeSummaryImpl { public: + enum class Kind + { + eSummaryString, + eScript, + eCallback, + eInternal + }; + + virtual + ~TypeSummaryImpl() = default; + + Kind + GetKind () const + { + return m_kind; + } + class Flags { public: - Flags () : m_flags (lldb::eTypeOptionCascade) {} @@ -162,6 +177,22 @@ namespace lldb_private { m_flags &= ~lldb::eTypeOptionHideChildren; return *this; } + + bool + GetHideEmptyAggregates () const + { + return (m_flags & lldb::eTypeOptionHideEmptyAggregates) == lldb::eTypeOptionHideEmptyAggregates; + } + + Flags& + SetHideEmptyAggregates (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionHideEmptyAggregates; + else + m_flags &= ~lldb::eTypeOptionHideEmptyAggregates; + return *this; + } bool GetDontShowValue () const @@ -243,31 +274,24 @@ namespace lldb_private { uint32_t m_flags; }; - typedef enum Type - { - eTypeUnknown, - eTypeString, - eTypeScript, - eTypeCallback - } Type; - - TypeSummaryImpl (const TypeSummaryImpl::Flags& flags); - bool Cascades () const { return m_flags.GetCascades(); } + bool SkipsPointers () const { return m_flags.GetSkipPointers(); } + bool SkipsReferences () const { return m_flags.GetSkipReferences(); } + bool NonCacheable () const { @@ -279,6 +303,12 @@ namespace lldb_private { { return !m_flags.GetDontShowChildren(); } + + virtual bool + DoesPrintEmptyAggregates () const + { + return !m_flags.GetHideEmptyAggregates(); + } virtual bool DoesPrintValue (ValueObject* valobj) const @@ -358,11 +388,6 @@ namespace lldb_private { m_flags.SetValue(value); } - virtual - ~TypeSummaryImpl () - { - } - // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for // extended periods of time and we trust the ValueObject to stay around for as long as it is required // for us to generate its summary @@ -374,12 +399,6 @@ namespace lldb_private { virtual std::string GetDescription () = 0; - virtual bool - IsScripted () = 0; - - virtual Type - GetType () = 0; - uint32_t& GetRevision () { @@ -387,14 +406,16 @@ namespace lldb_private { } typedef std::shared_ptr SharedPointer; - typedef bool(*SummaryCallback)(void*, ConstString, const lldb::TypeSummaryImplSP&); - typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const lldb::TypeSummaryImplSP&); protected: uint32_t m_my_revision; Flags m_flags; + TypeSummaryImpl (Kind kind, + const TypeSummaryImpl::Flags& flags); + private: + Kind m_kind; DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl); }; @@ -407,11 +428,8 @@ namespace lldb_private { StringSummaryFormat(const TypeSummaryImpl::Flags& flags, const char* f); - - virtual - ~StringSummaryFormat() - { - } + + ~StringSummaryFormat() override = default; const char* GetSummaryString () const @@ -422,25 +440,17 @@ namespace lldb_private { void SetSummaryString (const char* f); - virtual bool + bool FormatObject(ValueObject *valobj, std::string& dest, - const TypeSummaryOptions& options); - - virtual std::string - GetDescription(); - - virtual bool - IsScripted () - { - return false; - } + const TypeSummaryOptions& options) override; + std::string + GetDescription() override; - virtual Type - GetType () + static bool classof(const TypeSummaryImpl* S) { - return TypeSummaryImpl::eTypeString; + return S->GetKind() == Kind::eSummaryString; } private: @@ -452,9 +462,9 @@ namespace lldb_private { { // we should convert these to SBValue and SBStream if we ever cross // the boundary towards the external world - typedef bool (*Callback)(ValueObject&, - Stream&, - const TypeSummaryOptions&); + typedef std::function Callback; Callback m_impl; std::string m_description; @@ -462,7 +472,9 @@ namespace lldb_private { CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags, Callback impl, const char* description); - + + ~CXXFunctionSummaryFormat() override = default; + Callback GetBackendFunction () const { @@ -489,30 +501,18 @@ namespace lldb_private { else m_description.clear(); } + + bool + FormatObject(ValueObject *valobj, + std::string& dest, + const TypeSummaryOptions& options) override; - virtual - ~CXXFunctionSummaryFormat () - { - } - - virtual bool - FormatObject (ValueObject *valobj, - std::string& dest, - const TypeSummaryOptions& options); - - virtual std::string - GetDescription (); - - virtual bool - IsScripted () - { - return false; - } + std::string + GetDescription() override; - virtual Type - GetType () + static bool classof(const TypeSummaryImpl* S) { - return TypeSummaryImpl::eTypeCallback; + return S->GetKind() == Kind::eCallback; } typedef std::shared_ptr SharedPointer; @@ -521,8 +521,6 @@ namespace lldb_private { DISALLOW_COPY_AND_ASSIGN(CXXFunctionSummaryFormat); }; -#ifndef LLDB_DISABLE_PYTHON - // Python-based summaries, running script code to show data struct ScriptSummaryFormat : public TypeSummaryImpl { @@ -532,8 +530,10 @@ namespace lldb_private { ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags, const char *function_name, - const char* python_script = NULL); - + const char* python_script = nullptr); + + ~ScriptSummaryFormat() override = default; + const char* GetFunctionName () const { @@ -565,38 +565,24 @@ namespace lldb_private { m_python_script.clear(); } - virtual - ~ScriptSummaryFormat () - { - } - - virtual bool - FormatObject (ValueObject *valobj, - std::string& dest, - const TypeSummaryOptions& options); - - virtual std::string - GetDescription (); + bool + FormatObject(ValueObject *valobj, + std::string& dest, + const TypeSummaryOptions& options) override; - virtual bool - IsScripted () - { - return true; - } + std::string + GetDescription() override; - virtual Type - GetType () + static bool classof(const TypeSummaryImpl* S) { - return TypeSummaryImpl::eTypeScript; + return S->GetKind() == Kind::eScript; } typedef std::shared_ptr SharedPointer; - private: DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat); }; -#endif } // namespace lldb_private -#endif // lldb_TypeSummary_h_ +#endif // lldb_TypeSummary_h_ diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h index ff6691c9a1b8..90e5730288c4 100644 --- a/include/lldb/DataFormatters/TypeSynthetic.h +++ b/include/lldb/DataFormatters/TypeSynthetic.h @@ -1,4 +1,4 @@ -//===-- TypeSynthetic.h -------------------------------------------*- C++ -*-===// +//===-- TypeSynthetic.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,11 +14,13 @@ #include // C++ Includes +#include +#include +#include #include #include // Other libraries and framework includes - // Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" @@ -45,23 +47,27 @@ namespace lldb_private { } public: - SyntheticChildrenFrontEnd (ValueObject &backend) : m_backend(backend), m_valid(true) {} - + virtual - ~SyntheticChildrenFrontEnd () - { - } - + ~SyntheticChildrenFrontEnd() = default; + virtual size_t CalculateNumChildren () = 0; + + virtual size_t + CalculateNumChildren (uint32_t max) + { + auto count = CalculateNumChildren (); + return count <= max ? count : max; + } virtual lldb::ValueObjectSP GetChildAtIndex (size_t idx) = 0; - + virtual size_t GetIndexOfChildWithName (const ConstString &name) = 0; @@ -98,13 +104,13 @@ namespace lldb_private { CreateValueObjectFromAddress (const char* name, uint64_t address, const ExecutionContext& exe_ctx, - ClangASTType type); + CompilerType type); lldb::ValueObjectSP CreateValueObjectFromData (const char* name, const DataExtractor& data, const ExecutionContext& exe_ctx, - ClangASTType type); + CompilerType type); private: bool m_valid; @@ -117,29 +123,26 @@ namespace lldb_private { SyntheticValueProviderFrontEnd (ValueObject &backend) : SyntheticChildrenFrontEnd(backend) {} + + ~SyntheticValueProviderFrontEnd() override = default; + + size_t + CalculateNumChildren() override { return 0; } - virtual - ~SyntheticValueProviderFrontEnd () - { - } - - virtual size_t - CalculateNumChildren () { return 0; } - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx) { return nullptr; } + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override { return nullptr; } - virtual size_t - GetIndexOfChildWithName (const ConstString &name) { return UINT32_MAX; } + size_t + GetIndexOfChildWithName(const ConstString &name) override { return UINT32_MAX; } - virtual bool - Update () { return false; } + bool + Update() override { return false; } - virtual bool - MightHaveChildren () { return false; } + bool + MightHaveChildren () override { return false; } - virtual lldb::ValueObjectSP - GetSyntheticValue () = 0; + lldb::ValueObjectSP + GetSyntheticValue() override = 0; private: DISALLOW_COPY_AND_ASSIGN(SyntheticValueProviderFrontEnd); @@ -148,7 +151,6 @@ namespace lldb_private { class SyntheticChildren { public: - class Flags { public: @@ -272,27 +274,28 @@ namespace lldb_private { m_flags(flags) { } - + virtual - ~SyntheticChildren () - { - } - + ~SyntheticChildren() = default; + bool Cascades () const { return m_flags.GetCascades(); } + bool SkipsPointers () const { return m_flags.GetSkipPointers(); } + bool SkipsReferences () const { return m_flags.GetSkipReferences(); } + bool NonCacheable () const { @@ -345,7 +348,6 @@ namespace lldb_private { GetFrontEnd (ValueObject &backend) = 0; typedef std::shared_ptr SharedPointer; - typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); uint32_t& GetRevision () @@ -417,69 +419,67 @@ namespace lldb_private { SetExpressionPathAtIndex (size_t i, const std::string& path); bool - IsScripted () + IsScripted() override { return false; } std::string - GetDescription (); + GetDescription() override; class FrontEnd : public SyntheticChildrenFrontEnd { - private: - TypeFilterImpl* filter; public: - FrontEnd(TypeFilterImpl* flt, ValueObject &backend) : SyntheticChildrenFrontEnd(backend), filter(flt) {} - - virtual - ~FrontEnd () - { - } - - virtual size_t - CalculateNumChildren () + + ~FrontEnd() override = default; + + size_t + CalculateNumChildren() override { return filter->GetCount(); } - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx) + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override { if (idx >= filter->GetCount()) return lldb::ValueObjectSP(); return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true); } + + bool + Update() override { return false; } - virtual bool - Update() { return false; } - - virtual bool - MightHaveChildren () + bool + MightHaveChildren() override { return filter->GetCount() > 0; } - virtual size_t - GetIndexOfChildWithName (const ConstString &name); + size_t + GetIndexOfChildWithName(const ConstString &name) override; typedef std::shared_ptr SharedPointer; private: + TypeFilterImpl* filter; + DISALLOW_COPY_AND_ASSIGN(FrontEnd); }; - virtual SyntheticChildrenFrontEnd::AutoPointer - GetFrontEnd(ValueObject &backend) + SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) override { return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); } + typedef std::shared_ptr SharedPointer; + private: DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); }; @@ -487,11 +487,7 @@ namespace lldb_private { class CXXSyntheticChildren : public SyntheticChildren { public: - typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP); - protected: - CreateFrontEndCallback m_create_callback; - std::string m_description; - public: + typedef std::function CreateFrontEndCallback; CXXSyntheticChildren (const SyntheticChildren::Flags& flags, const char* description, CreateFrontEndCallback callback) : @@ -502,20 +498,24 @@ namespace lldb_private { } bool - IsScripted () + IsScripted() override { return false; } std::string - GetDescription (); + GetDescription() override; - virtual SyntheticChildrenFrontEnd::AutoPointer - GetFrontEnd (ValueObject &backend) + SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) override { return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP())); } + protected: + CreateFrontEndCallback m_create_callback; + std::string m_description; + private: DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren); }; @@ -528,9 +528,9 @@ namespace lldb_private { std::string m_python_code; public: - ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags, - const char* pclass, - const char* pcode = NULL) : + ScriptedSyntheticChildren(const SyntheticChildren::Flags& flags, + const char* pclass, + const char* pcode = nullptr) : SyntheticChildren(flags), m_python_class(), m_python_code() @@ -567,62 +567,63 @@ namespace lldb_private { } std::string - GetDescription (); + GetDescription() override; bool - IsScripted () + IsScripted() override { return true; } class FrontEnd : public SyntheticChildrenFrontEnd { - private: - std::string m_python_class; - StructuredData::ObjectSP m_wrapper_sp; - ScriptInterpreter *m_interpreter; public: - FrontEnd (std::string pclass, ValueObject &backend); + ~FrontEnd() override; + bool IsValid (); - virtual - ~FrontEnd (); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); + size_t + CalculateNumChildren() override; + + size_t + CalculateNumChildren(uint32_t max) override; - virtual bool - Update (); + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override; + + bool + Update() override; - virtual bool - MightHaveChildren (); + bool + MightHaveChildren() override; - virtual size_t - GetIndexOfChildWithName (const ConstString &name); + size_t + GetIndexOfChildWithName(const ConstString &name) override; - virtual lldb::ValueObjectSP - GetSyntheticValue (); + lldb::ValueObjectSP + GetSyntheticValue() override; typedef std::shared_ptr SharedPointer; private: + std::string m_python_class; + StructuredData::ObjectSP m_wrapper_sp; + ScriptInterpreter *m_interpreter; + DISALLOW_COPY_AND_ASSIGN(FrontEnd); }; - virtual SyntheticChildrenFrontEnd::AutoPointer - GetFrontEnd(ValueObject &backend) + SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) override { auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); if (synth_ptr && ((FrontEnd*)synth_ptr.get())->IsValid()) return synth_ptr; - return NULL; + return nullptr; } private: @@ -631,4 +632,4 @@ namespace lldb_private { #endif } // namespace lldb_private -#endif // lldb_TypeSynthetic_h_ +#endif // lldb_TypeSynthetic_h_ diff --git a/include/lldb/DataFormatters/TypeValidator.h b/include/lldb/DataFormatters/TypeValidator.h index d06fac01f824..f1f9a11049db 100644 --- a/include/lldb/DataFormatters/TypeValidator.h +++ b/include/lldb/DataFormatters/TypeValidator.h @@ -13,8 +13,8 @@ // C Includes // C++ Includes -#include #include +#include // Other libraries and framework includes @@ -150,7 +150,6 @@ public: TypeValidatorImpl (const Flags& flags = Flags()); typedef std::shared_ptr SharedPointer; - typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeValidatorImplSP&); virtual ~TypeValidatorImpl (); @@ -265,9 +264,8 @@ public: TypeValidatorImpl_CXX (ValidatorFunction f, std::string d, const TypeValidatorImpl::Flags& flags = Flags()); typedef std::shared_ptr SharedPointer; - typedef bool(*ValueCallback)(void*, ConstString, const TypeValidatorImpl_CXX::SharedPointer&); - virtual ~TypeValidatorImpl_CXX (); + ~TypeValidatorImpl_CXX() override; ValidatorFunction GetValidatorFunction () const @@ -281,17 +279,17 @@ public: m_validator_function = f; } - virtual TypeValidatorImpl::Type - GetType () + TypeValidatorImpl::Type + GetType() override { return TypeValidatorImpl::Type::eTypeCXX; } - virtual ValidationResult - FormatObject (ValueObject *valobj) const; + ValidationResult + FormatObject(ValueObject *valobj) const override; - virtual std::string - GetDescription(); + std::string + GetDescription() override; protected: std::string m_description; @@ -304,4 +302,4 @@ private: } // namespace lldb_private -#endif // lldb_TypeValidator_h_ +#endif // lldb_TypeValidator_h_ diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h index dc05fd482676..23d7ee2edf50 100644 --- a/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -18,232 +18,15 @@ #include "lldb/lldb-private.h" #include "lldb/lldb-public.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Core/Flags.h" +#include "lldb/DataFormatters/DumpValueObjectOptions.h" +#include "lldb/Symbol/CompilerType.h" -namespace lldb_private { +//#include +//#include +//#include -struct DumpValueObjectOptions -{ - uint32_t m_max_ptr_depth = 0; - uint32_t m_max_depth = UINT32_MAX; - lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; - uint32_t m_omit_summary_depth = 0; - lldb::Format m_format = lldb::eFormatDefault; - lldb::TypeSummaryImplSP m_summary_sp; - std::string m_root_valobj_name; - bool m_use_synthetic : 1; - bool m_scope_already_checked : 1; - bool m_flat_output : 1; - bool m_ignore_cap : 1; - bool m_show_types : 1; - bool m_show_location : 1; - bool m_use_objc : 1; - bool m_hide_root_type : 1; - bool m_hide_name : 1; - bool m_hide_value : 1; - bool m_run_validator : 1; - bool m_use_type_display_name : 1; - bool m_allow_oneliner_mode : 1; - - DumpValueObjectOptions() : - m_summary_sp(), - m_root_valobj_name(), - m_use_synthetic(true), - m_scope_already_checked(false), - m_flat_output(false), - m_ignore_cap(false), - m_show_types(false), - m_show_location(false), - m_use_objc(false), - m_hide_root_type(false), - m_hide_name(false), - m_hide_value(false), - m_run_validator(false), - m_use_type_display_name(true), - m_allow_oneliner_mode(true) - {} - - static const DumpValueObjectOptions - DefaultOptions() - { - static DumpValueObjectOptions g_default_options; - - return g_default_options; - } - - DumpValueObjectOptions (const DumpValueObjectOptions& rhs) = default; - - DumpValueObjectOptions (ValueObject& valobj); - - DumpValueObjectOptions& - SetMaximumPointerDepth(uint32_t depth = 0) - { - m_max_ptr_depth = depth; - return *this; - } - - DumpValueObjectOptions& - SetMaximumDepth(uint32_t depth = 0) - { - m_max_depth = depth; - return *this; - } - - DumpValueObjectOptions& - SetShowTypes(bool show = false) - { - m_show_types = show; - return *this; - } - - DumpValueObjectOptions& - SetShowLocation(bool show = false) - { - m_show_location = show; - return *this; - } - - DumpValueObjectOptions& - SetUseObjectiveC(bool use = false) - { - m_use_objc = use; - return *this; - } - - DumpValueObjectOptions& - SetShowSummary(bool show = true) - { - if (show == false) - SetOmitSummaryDepth(UINT32_MAX); - else - SetOmitSummaryDepth(0); - return *this; - } - - DumpValueObjectOptions& - SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues) - { - m_use_dynamic = dyn; - return *this; - } - - DumpValueObjectOptions& - SetUseSyntheticValue(bool use_synthetic = true) - { - m_use_synthetic = use_synthetic; - return *this; - } - - DumpValueObjectOptions& - SetScopeChecked(bool check = true) - { - m_scope_already_checked = check; - return *this; - } - - DumpValueObjectOptions& - SetFlatOutput(bool flat = false) - { - m_flat_output = flat; - return *this; - } - - DumpValueObjectOptions& - SetOmitSummaryDepth(uint32_t depth = 0) - { - m_omit_summary_depth = depth; - return *this; - } - - DumpValueObjectOptions& - SetIgnoreCap(bool ignore = false) - { - m_ignore_cap = ignore; - return *this; - } - - DumpValueObjectOptions& - SetRawDisplay() - { - SetUseSyntheticValue(false); - SetOmitSummaryDepth(UINT32_MAX); - SetIgnoreCap(true); - SetHideName(false); - SetHideValue(false); - SetUseTypeDisplayName(false); - SetAllowOnelinerMode(false); - return *this; - } - - DumpValueObjectOptions& - SetFormat (lldb::Format format = lldb::eFormatDefault) - { - m_format = format; - return *this; - } - - DumpValueObjectOptions& - SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP()) - { - m_summary_sp = summary; - return *this; - } - - DumpValueObjectOptions& - SetRootValueObjectName (const char* name = NULL) - { - if (name) - m_root_valobj_name.assign(name); - else - m_root_valobj_name.clear(); - return *this; - } - - DumpValueObjectOptions& - SetHideRootType (bool hide_root_type = false) - { - m_hide_root_type = hide_root_type; - return *this; - } - - DumpValueObjectOptions& - SetHideName (bool hide_name = false) - { - m_hide_name = hide_name; - return *this; - } - - DumpValueObjectOptions& - SetHideValue (bool hide_value = false) - { - m_hide_value = hide_value; - return *this; - } - - DumpValueObjectOptions& - SetRunValidator (bool run = true) - { - m_run_validator = run; - return *this; - } - - DumpValueObjectOptions& - SetUseTypeDisplayName (bool dis = false) - { - m_use_type_display_name = dis; - return *this; - } - - DumpValueObjectOptions& - SetAllowOnelinerMode (bool oneliner = false) - { - m_allow_oneliner_mode = oneliner; - return *this; - } - -}; +namespace lldb_private { class ValueObjectPrinter { @@ -262,14 +45,19 @@ public: PrintValueObject (); protected: + typedef std::set InstancePointersSet; + typedef std::shared_ptr InstancePointersSetSP; + InstancePointersSetSP m_printed_instance_pointers; + // only this class (and subclasses, if any) should ever be concerned with // the depth mechanism ValueObjectPrinter (ValueObject* valobj, Stream* s, const DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth); + const DumpValueObjectOptions::PointerDepth& ptr_depth, + uint32_t curr_depth, + InstancePointersSetSP printed_instance_pointers); // we should actually be using delegating constructors here // but some versions of GCC still have trouble with those @@ -277,8 +65,9 @@ protected: Init (ValueObject* valobj, Stream* s, const DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth); + const DumpValueObjectOptions::PointerDepth& ptr_depth, + uint32_t curr_depth, + InstancePointersSetSP printed_instance_pointers); bool GetMostSpecializedValue (); @@ -298,12 +87,18 @@ protected: bool IsNil (); + bool + IsUninitialized (); + bool IsPtr (); bool IsRef (); + bool + IsInstancePointer (); + bool IsAggregate (); @@ -316,17 +111,18 @@ protected: bool PrintLocationIfNeeded (); - bool - PrintTypeIfNeeded (); + void + PrintDecl (); bool - PrintNameIfNeeded (bool show_type); + CheckScopeIfNeeded (); bool - CheckScopeIfNeeded (); + ShouldPrintEmptyBrackets (bool value_printed, + bool summary_printed); TypeSummaryImpl* - GetSummaryFormatter (); + GetSummaryFormatter (bool null_if_omitted = true); void GetValueSummaryError (std::string& value, @@ -343,7 +139,10 @@ protected: bool ShouldPrintChildren (bool is_failed_description, - uint32_t& curr_ptr_depth); + DumpValueObjectOptions::PointerDepth& curr_ptr_depth); + + bool + ShouldExpandEmptyAggregates (); ValueObject* GetValueObjectForChildrenGeneration (); @@ -356,13 +155,15 @@ protected: void PrintChild (lldb::ValueObjectSP child_sp, - uint32_t curr_ptr_depth); + const DumpValueObjectOptions::PointerDepth& curr_ptr_depth); uint32_t GetMaxNumChildrenToPrint (bool& print_dotdotdot); void - PrintChildren (uint32_t curr_ptr_depth); + PrintChildren (bool value_printed, + bool summary_printed, + const DumpValueObjectOptions::PointerDepth& curr_ptr_depth); void PrintChildrenIfNeeded (bool value_printed, @@ -376,20 +177,23 @@ private: ValueObject *m_orig_valobj; ValueObject *m_valobj; Stream *m_stream; - DumpValueObjectOptions options; + DumpValueObjectOptions m_options; Flags m_type_flags; - ClangASTType m_clang_type; - uint32_t m_ptr_depth; + CompilerType m_compiler_type; + DumpValueObjectOptions::PointerDepth m_ptr_depth; uint32_t m_curr_depth; LazyBool m_should_print; LazyBool m_is_nil; + LazyBool m_is_uninit; LazyBool m_is_ptr; LazyBool m_is_ref; LazyBool m_is_aggregate; + LazyBool m_is_instance_ptr; std::pair m_summary_formatter; std::string m_value; std::string m_summary; std::string m_error; + bool m_val_summary_ok; std::pair m_validation; friend struct StringSummaryFormat; diff --git a/include/lldb/DataFormatters/VectorIterator.h b/include/lldb/DataFormatters/VectorIterator.h new file mode 100644 index 000000000000..3d96ee4c093b --- /dev/null +++ b/include/lldb/DataFormatters/VectorIterator.h @@ -0,0 +1,53 @@ +//===-- VectorIterator.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_VectorIterator_h_ +#define liblldb_VectorIterator_h_ + +#include "lldb/lldb-forward.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + namespace formatters + { + class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, + ConstString item_name); + + size_t + CalculateNumChildren() override; + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override; + + bool + Update() override; + + bool + MightHaveChildren() override; + + size_t + GetIndexOfChildWithName(const ConstString &name) override; + + ~VectorIteratorSyntheticFrontEnd() override; + + private: + ExecutionContextRef m_exe_ctx_ref; + ConstString m_item_name; + lldb::ValueObjectSP m_item_sp; + }; + + } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CF_h_ diff --git a/include/lldb/Expression/ASTDumper.h b/include/lldb/Expression/ASTDumper.h deleted file mode 100644 index 47f7ea460b87..000000000000 --- a/include/lldb/Expression/ASTDumper.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- ASTDumper.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_ASTDumper_h_ -#define liblldb_ASTDumper_h_ - -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/TypeVisitor.h" - -#include "lldb/Core/Stream.h" -#include "llvm/ADT/DenseSet.h" - -namespace lldb_private -{ - -class ASTDumper -{ -public: - ASTDumper (clang::Decl *decl); - ASTDumper (clang::DeclContext *decl_ctx); - ASTDumper (const clang::Type *type); - ASTDumper (clang::QualType type); - ASTDumper (lldb::clang_type_t type); - ASTDumper (const ClangASTType &clang_type); - - const char *GetCString(); - void ToSTDERR(); - void ToLog(Log *log, const char *prefix); - void ToStream(lldb::StreamSP &stream); -private: - std::string m_dump; -}; - -} // namespace lldb_private - -#endif diff --git a/include/lldb/Expression/ASTResultSynthesizer.h b/include/lldb/Expression/ASTResultSynthesizer.h deleted file mode 100644 index 410a862fc12a..000000000000 --- a/include/lldb/Expression/ASTResultSynthesizer.h +++ /dev/null @@ -1,184 +0,0 @@ -//===-- ASTResultSynthesizer.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_ASTResultSynthesizer_h_ -#define liblldb_ASTResultSynthesizer_h_ - -#include "clang/Sema/SemaConsumer.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Symbol/TaggedASTType.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" -/// @brief Adds a result variable declaration to the ASTs for an expression. -/// -/// Users expect the expression "i + 3" to return a result, even if a result -/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds -/// a result variable to the expression, transforming it to -/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the -/// resulting variable is mapped to the right piece of memory. -/// ASTResultSynthesizer's job is to add the variable and its initialization to -/// the ASTs for the expression, and it does so by acting as a SemaConsumer for -/// Clang. -//---------------------------------------------------------------------- -class ASTResultSynthesizer : public clang::SemaConsumer -{ -public: - //---------------------------------------------------------------------- - /// Constructor - /// - /// @param[in] passthrough - /// Since the ASTs must typically go through to the Clang code generator - /// in order to produce LLVM IR, this SemaConsumer must allow them to - /// pass to the next step in the chain after processing. Passthrough is - /// the next ASTConsumer, or NULL if none is required. - /// - /// @param[in] target - /// The target, which contains the persistent variable store and the - /// AST importer. - //---------------------------------------------------------------------- - ASTResultSynthesizer(clang::ASTConsumer *passthrough, - Target &target); - - //---------------------------------------------------------------------- - /// Destructor - //---------------------------------------------------------------------- - ~ASTResultSynthesizer(); - - //---------------------------------------------------------------------- - /// Link this consumer with a particular AST context - /// - /// @param[in] Context - /// This AST context will be used for types and identifiers, and also - /// forwarded to the passthrough consumer, if one exists. - //---------------------------------------------------------------------- - void Initialize(clang::ASTContext &Context); - - //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code - /// - /// @param[in] D - /// The list of Decls to search. These may contain LinkageSpecDecls, - /// which need to be searched recursively. That job falls to - /// TransformTopLevelDecl. - //---------------------------------------------------------------------- - bool HandleTopLevelDecl(clang::DeclGroupRef D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTranslationUnit(clang::ASTContext &Ctx); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTagDeclDefinition(clang::TagDecl *D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void CompleteTentativeDefinition(clang::VarDecl *D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void PrintStats(); - - //---------------------------------------------------------------------- - /// Set the Sema object to use when performing transforms, and pass it on - /// - /// @param[in] S - /// The Sema to use. Because Sema isn't externally visible, this class - /// casts it to an Action for actual use. - //---------------------------------------------------------------------- - void InitializeSema(clang::Sema &S); - - //---------------------------------------------------------------------- - /// Reset the Sema to NULL now that transformations are done - //---------------------------------------------------------------------- - void ForgetSema(); -private: - //---------------------------------------------------------------------- - /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing - /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on - /// anything that was found - /// - /// @param[in] D - /// The Decl to hunt. - //---------------------------------------------------------------------- - void TransformTopLevelDecl(clang::Decl *D); - - //---------------------------------------------------------------------- - /// Process an Objective-C method and produce the result variable and - /// initialization - /// - /// @param[in] MethodDecl - /// The method to process. - //---------------------------------------------------------------------- - bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); - - //---------------------------------------------------------------------- - /// Process a function and produce the result variable and initialization - /// - /// @param[in] FunDecl - /// The function to process. - //---------------------------------------------------------------------- - bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); - - //---------------------------------------------------------------------- - /// Process a function body and produce the result variable and - /// initialization - /// - /// @param[in] Body - /// The body of the function. - /// - /// @param[in] DC - /// The DeclContext of the function, into which the result variable - /// is inserted. - //---------------------------------------------------------------------- - bool SynthesizeBodyResult(clang::CompoundStmt *Body, - clang::DeclContext *DC); - - //---------------------------------------------------------------------- - /// Given a DeclContext for a function or method, find all types - /// declared in the context and record any persistent types found. - /// - /// @param[in] FunDeclCtx - /// The context for the function to process. - //---------------------------------------------------------------------- - void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); - - //---------------------------------------------------------------------- - /// Given a TypeDecl, if it declares a type whose name starts with a - /// dollar sign, register it as a pointer type in the target's scratch - /// AST context. - /// - /// @param[in] Body - /// The body of the function. - //---------------------------------------------------------------------- - void MaybeRecordPersistentType(clang::TypeDecl *D); - - clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. - clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. - clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. - Target &m_target; ///< The target, which contains the persistent variable store and the - clang::Sema *m_sema; ///< The Sema to use. -}; - -} - -#endif diff --git a/include/lldb/Expression/ASTStructExtractor.h b/include/lldb/Expression/ASTStructExtractor.h deleted file mode 100644 index 25193744c9e0..000000000000 --- a/include/lldb/Expression/ASTStructExtractor.h +++ /dev/null @@ -1,156 +0,0 @@ -//===-- ASTStructExtractor.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_ASTStructExtractor_h_ -#define liblldb_ASTStructExtractor_h_ - -#include "clang/Sema/SemaConsumer.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangFunction.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" -/// @brief Extracts and describes the argument structure for a wrapped function. -/// -/// This pass integrates with ClangFunction, which calls functions with custom -/// sets of arguments. To avoid having to implement the full calling convention -/// for the target's architecture, ClangFunction writes a simple wrapper -/// function that takes a pointer to an argument structure that contains room -/// for the address of the function to be called, the values of all its -/// arguments, and room for the function's return value. -/// -/// The definition of this struct is itself in the body of the wrapper function, -/// so Clang does the structure layout itself. ASTStructExtractor reads through -/// the AST for the wrapper function and finds the struct. -//---------------------------------------------------------------------- -class ASTStructExtractor : public clang::SemaConsumer -{ -public: - //---------------------------------------------------------------------- - /// Constructor - /// - /// @param[in] passthrough - /// Since the ASTs must typically go through to the Clang code generator - /// in order to produce LLVM IR, this SemaConsumer must allow them to - /// pass to the next step in the chain after processing. Passthrough is - /// the next ASTConsumer, or NULL if none is required. - /// - /// @param[in] struct_name - /// The name of the structure to extract from the wrapper function. - /// - /// @param[in] function - /// The caller object whose members should be populated with information - /// about the argument struct. ClangFunction friends ASTStructExtractor - /// for this purpose. - //---------------------------------------------------------------------- - ASTStructExtractor(clang::ASTConsumer *passthrough, - const char *struct_name, - ClangFunction &function); - - //---------------------------------------------------------------------- - /// Destructor - //---------------------------------------------------------------------- - virtual ~ASTStructExtractor(); - - //---------------------------------------------------------------------- - /// Link this consumer with a particular AST context - /// - /// @param[in] Context - /// This AST context will be used for types and identifiers, and also - /// forwarded to the passthrough consumer, if one exists. - //---------------------------------------------------------------------- - void Initialize(clang::ASTContext &Context); - - //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code - /// - /// @param[in] D - /// The list of Decls to search. These may contain LinkageSpecDecls, - /// which need to be searched recursively. That job falls to - /// TransformTopLevelDecl. - //---------------------------------------------------------------------- - bool HandleTopLevelDecl(clang::DeclGroupRef D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTranslationUnit(clang::ASTContext &Ctx); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleTagDeclDefinition(clang::TagDecl *D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void CompleteTentativeDefinition(clang::VarDecl *D); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void HandleVTable(clang::CXXRecordDecl *RD); - - //---------------------------------------------------------------------- - /// Passthrough stub - //---------------------------------------------------------------------- - void PrintStats(); - - //---------------------------------------------------------------------- - /// Set the Sema object to use when performing transforms, and pass it on - /// - /// @param[in] S - /// The Sema to use. Because Sema isn't externally visible, this class - /// casts it to an Action for actual use. - //---------------------------------------------------------------------- - void InitializeSema(clang::Sema &S); - - //---------------------------------------------------------------------- - /// Reset the Sema to NULL now that transformations are done - //---------------------------------------------------------------------- - void ForgetSema(); -private: - //---------------------------------------------------------------------- - /// Hunt the given FunctionDecl for the argument struct and place - /// information about it into m_function - /// - /// @param[in] F - /// The FunctionDecl to hunt. - //---------------------------------------------------------------------- - void - ExtractFromFunctionDecl(clang::FunctionDecl* F); - - //---------------------------------------------------------------------- - /// Hunt the given Decl for FunctionDecls named the same as the wrapper - /// function name, recursing as necessary through LinkageSpecDecls, and - /// calling ExtractFromFunctionDecl on anything that was found - /// - /// @param[in] D - /// The Decl to hunt. - //---------------------------------------------------------------------- - void - ExtractFromTopLevelDecl(clang::Decl* D); - - clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. - clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. - clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. - clang::Sema *m_sema; ///< The Sema to use. - clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable. - - ClangFunction &m_function; ///< The function to populate with information about the argument structure. - std::string m_struct_name; ///< The name of the structure to extract. -}; - -} - -#endif diff --git a/include/lldb/Expression/ClangASTSource.h b/include/lldb/Expression/ClangASTSource.h deleted file mode 100644 index 46140d2f2e64..000000000000 --- a/include/lldb/Expression/ClangASTSource.h +++ /dev/null @@ -1,525 +0,0 @@ -//===-- ClangASTSource.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_ClangASTSource_h_ -#define liblldb_ClangASTSource_h_ - -#include - -#include "clang/Basic/IdentifierTable.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" -#include "lldb/Symbol/ClangASTImporter.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Target/Target.h" - -#include "llvm/ADT/SmallSet.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" -/// @brief Provider for named objects defined in the debug info for Clang -/// -/// As Clang parses an expression, it may encounter names that are not -/// defined inside the expression, including variables, functions, and -/// types. Clang knows the name it is looking for, but nothing else. -/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) -/// to Clang for these names, consulting the ClangExpressionDeclMap to do -/// the actual lookups. -//---------------------------------------------------------------------- -class ClangASTSource : - public ClangExternalASTSourceCommon, - public ClangASTImporter::MapCompleter -{ -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] declMap - /// A reference to the LLDB object that handles entity lookup. - //------------------------------------------------------------------ - ClangASTSource (const lldb::TargetSP &target) : - m_import_in_progress (false), - m_lookups_enabled (false), - m_target (target), - m_ast_context (NULL), - m_active_lexical_decls (), - m_active_lookups () - { - m_ast_importer = m_target->GetClangASTImporter(); - } - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangASTSource(); - - //------------------------------------------------------------------ - /// Interface stubs. - //------------------------------------------------------------------ - clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } - clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } - clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } - uint32_t GetNumExternalSelectors () override { return 0; } - clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override - { return NULL; } - void MaterializeVisibleDecls (const clang::DeclContext *DC) - { return; } - - void InstallASTContext (clang::ASTContext *ast_context) - { - m_ast_context = ast_context; - m_ast_importer->InstallMapCompleter(ast_context, *this); - } - - // - // APIs for ExternalASTSource - // - - //------------------------------------------------------------------ - /// Look up all Decls that match a particular name. Only handles - /// Identifiers and DeclContexts that are either NamespaceDecls or - /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with - /// the result. - /// - /// The work for this function is done by - /// void FindExternalVisibleDecls (NameSearchContext &); - /// - /// @param[in] DC - /// The DeclContext to register the found Decls in. - /// - /// @param[in] Name - /// The name to find entries for. - /// - /// @return - /// Whatever SetExternalVisibleDeclsForName returns. - //------------------------------------------------------------------ - bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; - - //------------------------------------------------------------------ - /// Enumerate all Decls in a given lexical context. - /// - /// @param[in] DC - /// The DeclContext being searched. - /// - /// @param[in] isKindWeWant - /// If non-NULL, a callback function that returns true given the - /// DeclKinds of desired Decls, and false otherwise. - /// - /// @param[in] Decls - /// A vector that is filled in with matching Decls. - //------------------------------------------------------------------ - clang::ExternalLoadResult FindExternalLexicalDecls(const clang::DeclContext *DC, - bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &Decls) override; - - //------------------------------------------------------------------ - /// Specify the layout of the contents of a RecordDecl. - /// - /// @param[in] Record - /// The record (in the parser's AST context) that needs to be - /// laid out. - /// - /// @param[out] Size - /// The total size of the record in bits. - /// - /// @param[out] Alignment - /// The alignment of the record in bits. - /// - /// @param[in] FieldOffsets - /// A map that must be populated with pairs of the record's - /// fields (in the parser's AST context) and their offsets - /// (measured in bits). - /// - /// @param[in] BaseOffsets - /// A map that must be populated with pairs of the record's - /// C++ concrete base classes (in the parser's AST context, - /// and only if the record is a CXXRecordDecl and has base - /// classes) and their offsets (measured in bytes). - /// - /// @param[in] VirtualBaseOffsets - /// A map that must be populated with pairs of the record's - /// C++ virtual base classes (in the parser's AST context, - /// and only if the record is a CXXRecordDecl and has base - /// classes) and their offsets (measured in bytes). - /// - /// @return - /// True <=> the layout is valid. - //----------------------------------------------------------------- - bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets) override; - - //------------------------------------------------------------------ - /// Complete a TagDecl. - /// - /// @param[in] Tag - /// The Decl to be completed in place. - //------------------------------------------------------------------ - void CompleteType(clang::TagDecl *Tag) override; - - //------------------------------------------------------------------ - /// Complete an ObjCInterfaceDecl. - /// - /// @param[in] Class - /// The Decl to be completed in place. - //------------------------------------------------------------------ - void CompleteType(clang::ObjCInterfaceDecl *Class) override; - - //------------------------------------------------------------------ - /// Called on entering a translation unit. Tells Clang by calling - /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() - /// that this object has something to say about undefined names. - /// - /// @param[in] ASTConsumer - /// Unused. - //------------------------------------------------------------------ - void StartTranslationUnit(clang::ASTConsumer *Consumer) override; - - // - // APIs for NamespaceMapCompleter - // - - //------------------------------------------------------------------ - /// Look up the modules containing a given namespace and put the - /// appropriate entries in the namespace map. - /// - /// @param[in] namespace_map - /// The map to be completed. - /// - /// @param[in] name - /// The name of the namespace to be found. - /// - /// @param[in] parent_map - /// The map for the namespace's parent namespace, if there is - /// one. - //------------------------------------------------------------------ - void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, - ClangASTImporter::NamespaceMapSP &parent_map) const override; - - // - // Helper APIs - // - - clang::NamespaceDecl * - AddNamespace (NameSearchContext &context, - ClangASTImporter::NamespaceMapSP &namespace_decls); - - //------------------------------------------------------------------ - /// The worker function for FindExternalVisibleDeclsByName. - /// - /// @param[in] context - /// The NameSearchContext to use when filing results. - //------------------------------------------------------------------ - virtual void FindExternalVisibleDecls (NameSearchContext &context); - - void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } - bool GetImportInProgress () { return m_import_in_progress; } - - void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } - bool GetLookupsEnabled () { return m_lookups_enabled; } - - //---------------------------------------------------------------------- - /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" - /// @brief Proxy for ClangASTSource - /// - /// Clang AST contexts like to own their AST sources, so this is a - /// state-free proxy object. - //---------------------------------------------------------------------- - class ClangASTSourceProxy : public ClangExternalASTSourceCommon - { - public: - ClangASTSourceProxy (ClangASTSource &original) : - m_original(original) - { - } - - bool - FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override - { - return m_original.FindExternalVisibleDeclsByName(DC, Name); - } - - clang::ExternalLoadResult - FindExternalLexicalDecls(const clang::DeclContext *DC, bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &Decls) override - { - return m_original.FindExternalLexicalDecls(DC, isKindWeWant, Decls); - } - - void - CompleteType(clang::TagDecl *Tag) override - { - return m_original.CompleteType(Tag); - } - - void - CompleteType(clang::ObjCInterfaceDecl *Class) override - { - return m_original.CompleteType(Class); - } - - bool - layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, - llvm::DenseMap &FieldOffsets, - llvm::DenseMap &BaseOffsets, - llvm::DenseMap &VirtualBaseOffsets) override - { - return m_original.layoutRecordType(Record, - Size, - Alignment, - FieldOffsets, - BaseOffsets, - VirtualBaseOffsets); - } - - void - StartTranslationUnit(clang::ASTConsumer *Consumer) override - { - return m_original.StartTranslationUnit(Consumer); - } - - ClangASTMetadata * - GetMetadata(const void * object) - { - return m_original.GetMetadata(object); - } - - void - SetMetadata(const void * object, ClangASTMetadata &metadata) - { - return m_original.SetMetadata(object, metadata); - } - - bool - HasMetadata(const void * object) - { - return m_original.HasMetadata(object); - } - private: - ClangASTSource &m_original; - }; - - clang::ExternalASTSource *CreateProxy() - { - return new ClangASTSourceProxy(*this); - } - -protected: - //------------------------------------------------------------------ - /// Look for the complete version of an Objective-C interface, and - /// return it if found. - /// - /// @param[in] interface_decl - /// An ObjCInterfaceDecl that may not be the complete one. - /// - /// @return - /// NULL if the complete interface couldn't be found; - /// the complete interface otherwise. - //------------------------------------------------------------------ - clang::ObjCInterfaceDecl * - GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); - - //------------------------------------------------------------------ - /// Find all entities matching a given name in a given module, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @param[in] module - /// If non-NULL, the module to query. - /// - /// @param[in] namespace_decl - /// If valid and module is non-NULL, the parent namespace. - /// - /// @param[in] current_id - /// The ID for the current FindExternalVisibleDecls invocation, - /// for logging purposes. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module, - ClangNamespaceDecl &namespace_decl, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Find all Objective-C methods matching a given selector. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// Its m_decl_name contains the selector and its m_decl_context - /// is the containing object. - //------------------------------------------------------------------ - void - FindObjCMethodDecls (NameSearchContext &context); - - //------------------------------------------------------------------ - /// Find all Objective-C properties and ivars with a given name. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// Its m_decl_name contains the name and its m_decl_context - /// is the containing object. - //------------------------------------------------------------------ - void - FindObjCPropertyAndIvarDecls (NameSearchContext &context); - - //------------------------------------------------------------------ - /// A wrapper for ClangASTContext::CopyType that sets a flag that - /// indicates that we should not respond to queries during import. - /// - /// @param[in] dest_context - /// The target AST context, typically the parser's AST context. - /// - /// @param[in] source_context - /// The source AST context, typically the AST context of whatever - /// symbol file the type was found in. - /// - /// @param[in] clang_type - /// The source type. - /// - /// @return - /// The imported type. - //------------------------------------------------------------------ - ClangASTType - GuardedCopyType (const ClangASTType &src_type); - - friend struct NameSearchContext; - - bool m_import_in_progress; - bool m_lookups_enabled; - - const lldb::TargetSP m_target; ///< The target to use in finding variables and types. - clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. - ClangASTImporter *m_ast_importer; ///< The target's AST importer. - std::set m_active_lexical_decls; - std::set m_active_lookups; -}; - -//---------------------------------------------------------------------- -/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" -/// @brief Container for all objects relevant to a single name lookup -/// -/// LLDB needs to create Decls for entities it finds. This class communicates -/// what name is being searched for and provides helper functions to construct -/// Decls given appropriate type information. -//---------------------------------------------------------------------- -struct NameSearchContext { - ClangASTSource &m_ast_source; ///< The AST source making the request - llvm::SmallVectorImpl &m_decls; ///< The list of declarations already constructed - ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules - const clang::DeclarationName &m_decl_name; ///< The name being looked for - const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into - llvm::SmallSet m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts - - struct { - bool variable : 1; - bool function_with_type_info : 1; - bool function : 1; - } m_found; - - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] astSource - /// A reference to the AST source making a request. - /// - /// @param[in] decls - /// A reference to a list into which new Decls will be placed. This - /// list is typically empty when the function is called. - /// - /// @param[in] name - /// The name being searched for (always an Identifier). - /// - /// @param[in] dc - /// The DeclContext to register Decls in. - //------------------------------------------------------------------ - NameSearchContext (ClangASTSource &astSource, - llvm::SmallVectorImpl &decls, - clang::DeclarationName &name, - const clang::DeclContext *dc) : - m_ast_source(astSource), - m_decls(decls), - m_decl_name(name), - m_decl_context(dc) - { - memset(&m_found, 0, sizeof(m_found)); - } - - //------------------------------------------------------------------ - /// Create a VarDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] type - /// The opaque QualType for the VarDecl being registered. - //------------------------------------------------------------------ - clang::NamedDecl *AddVarDecl(const ClangASTType &type); - - //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] type - /// The opaque QualType for the FunDecl being registered. - /// - /// @param[in] extern_c - /// If true, build an extern "C" linkage specification for this. - //------------------------------------------------------------------ - clang::NamedDecl *AddFunDecl(const ClangASTType &type, - bool extern_c = false); - - //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and generic - /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the - /// right places. - //------------------------------------------------------------------ - clang::NamedDecl *AddGenericFunDecl(); - - //------------------------------------------------------------------ - /// Create a TypeDecl with the name being searched for and the provided - /// type and register it in the right places. - /// - /// @param[in] type - /// The opaque QualType for the TypeDecl being registered. - //------------------------------------------------------------------ - clang::NamedDecl *AddTypeDecl(const ClangASTType &clang_type); - - - //------------------------------------------------------------------ - /// Add Decls from the provided DeclContextLookupResult to the list - /// of results. - /// - /// @param[in] result - /// The DeclContextLookupResult, usually returned as the result - /// of querying a DeclContext. - //------------------------------------------------------------------ - void AddLookupResult (clang::DeclContextLookupResult result); - - //------------------------------------------------------------------ - /// Add a NamedDecl to the list of results. - /// - /// @param[in] decl - /// The NamedDecl, usually returned as the result - /// of querying a DeclContext. - //------------------------------------------------------------------ - void AddNamedDecl (clang::NamedDecl *decl); -}; - -} - -#endif diff --git a/include/lldb/Expression/ClangExpression.h b/include/lldb/Expression/ClangExpression.h deleted file mode 100644 index 6e831e4471e8..000000000000 --- a/include/lldb/Expression/ClangExpression.h +++ /dev/null @@ -1,153 +0,0 @@ -//===-- ClangExpression.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_ClangExpression_h_ -#define liblldb_ClangExpression_h_ - -// C Includes -// C++ Includes -#include -#include -#include - -// Other libraries and framework includes -// Project includes - -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Target/Process.h" - -namespace lldb_private { - -class RecordingMemoryManager; - -//---------------------------------------------------------------------- -/// @class ClangExpression ClangExpression.h "lldb/Expression/ClangExpression.h" -/// @brief Encapsulates a single expression for use with Clang -/// -/// LLDB uses expressions for various purposes, notably to call functions -/// and as a backend for the expr command. ClangExpression encapsulates -/// the objects needed to parse and interpret or JIT an expression. It -/// uses the Clang parser to produce LLVM IR from the expression. -//---------------------------------------------------------------------- -class ClangExpression -{ -public: - enum ResultType { - eResultTypeAny, - eResultTypeId - }; - - ClangExpression () : - m_jit_process_wp(), - m_jit_start_addr (LLDB_INVALID_ADDRESS), - m_jit_end_addr (LLDB_INVALID_ADDRESS) - { - } - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual ~ClangExpression () - { - } - - //------------------------------------------------------------------ - /// Return the string that the parser should parse. Must be a full - /// translation unit. - //------------------------------------------------------------------ - virtual const char * - Text () = 0; - - //------------------------------------------------------------------ - /// Return the function name that should be used for executing the - /// expression. Text() should contain the definition of this - /// function. - //------------------------------------------------------------------ - virtual const char * - FunctionName () = 0; - - //------------------------------------------------------------------ - /// Return the language that should be used when parsing. To use - /// the default, return eLanguageTypeUnknown. - //------------------------------------------------------------------ - virtual lldb::LanguageType - Language () - { - return lldb::eLanguageTypeUnknown; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - virtual ClangExpressionDeclMap * - DeclMap () = 0; - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - virtual clang::ASTConsumer * - ASTTransformer (clang::ASTConsumer *passthrough) = 0; - - //------------------------------------------------------------------ - /// Return the desired result type of the function, or - /// eResultTypeAny if indifferent. - //------------------------------------------------------------------ - virtual ResultType - DesiredResultType () - { - return eResultTypeAny; - } - - //------------------------------------------------------------------ - /// Flags - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Return true if validation code should be inserted into the - /// expression. - //------------------------------------------------------------------ - virtual bool - NeedsValidation () = 0; - - //------------------------------------------------------------------ - /// Return true if external variables in the expression should be - /// resolved. - //------------------------------------------------------------------ - virtual bool - NeedsVariableResolution () = 0; - - //------------------------------------------------------------------ - /// Return the address of the function's JIT-compiled code, or - /// LLDB_INVALID_ADDRESS if the function is not JIT compiled - //------------------------------------------------------------------ - lldb::addr_t - StartAddress () - { - return m_jit_start_addr; - } - -protected: - - lldb::ProcessWP m_jit_process_wp; - lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. - lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. - -}; - -} // namespace lldb_private - -#endif // liblldb_ClangExpression_h_ diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h deleted file mode 100644 index f24500ab5237..000000000000 --- a/include/lldb/Expression/ClangExpressionDeclMap.h +++ /dev/null @@ -1,705 +0,0 @@ -//===-- ClangExpressionDeclMap.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_ClangExpressionDeclMap_h_ -#define liblldb_ClangExpressionDeclMap_h_ - -// C Includes -#include -#include - -// C++ Includes -#include - -// Other libraries and framework includes -// Project includes -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/DenseMap.h" -#include "clang/AST/Decl.h" -#include "lldb/lldb-public.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/Materializer.h" -#include "lldb/Symbol/TaggedASTType.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/ExecutionContext.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" -/// @brief Manages named entities that are defined in LLDB's debug information. -/// -/// The Clang parser uses the ClangASTSource as an interface to request named -/// entities from outside an expression. The ClangASTSource reports back, listing -/// all possible objects corresponding to a particular name. But it in turn -/// relies on ClangExpressionDeclMap, which performs several important functions. -/// -/// First, it records what variables and functions were looked up and what Decls -/// were returned for them. -/// -/// Second, it constructs a struct on behalf of IRForTarget, recording which -/// variables should be placed where and relaying this information back so that -/// IRForTarget can generate context-independent code. -/// -/// Third, it "materializes" this struct on behalf of the expression command, -/// finding the current values of each variable and placing them into the -/// struct so that it can be passed to the JITted version of the IR. -/// -/// Fourth and finally, it "dematerializes" the struct after the JITted code has -/// has executed, placing the new values back where it found the old ones. -//---------------------------------------------------------------------- -class ClangExpressionDeclMap : - public ClangASTSource -{ -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] keep_result_in_memory - /// If true, inhibits the normal deallocation of the memory for - /// the result persistent variable, and instead marks the variable - /// as persisting. - /// - /// @param[in] exe_ctx - /// The execution context to use when parsing. - //------------------------------------------------------------------ - ClangExpressionDeclMap (bool keep_result_in_memory, - ExecutionContext &exe_ctx); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangExpressionDeclMap (); - - //------------------------------------------------------------------ - /// Enable the state needed for parsing and IR transformation. - /// - /// @param[in] exe_ctx - /// The execution context to use when finding types for variables. - /// Also used to find a "scratch" AST context to store result types. - /// - /// @param[in] materializer - /// If non-NULL, the materializer to populate with information about - /// the variables to use - /// - /// @return - /// True if parsing is possible; false if it is unsafe to continue. - //------------------------------------------------------------------ - bool - WillParse (ExecutionContext &exe_ctx, - Materializer *materializer); - - void - InstallCodeGenerator (clang::ASTConsumer *code_gen); - - //------------------------------------------------------------------ - /// [Used by ClangExpressionParser] For each variable that had an unknown - /// type at the beginning of parsing, determine its final type now. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - ResolveUnknownTypes(); - - //------------------------------------------------------------------ - /// Disable the state needed for parsing and IR transformation. - //------------------------------------------------------------------ - void - DidParse (); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Add a variable to the list of persistent - /// variables for the process. - /// - /// @param[in] decl - /// The Clang declaration for the persistent variable, used for - /// lookup during parsing. - /// - /// @param[in] name - /// The name of the persistent variable, usually $something. - /// - /// @param[in] type - /// The type of the variable, in the Clang parser's context. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - AddPersistentVariable (const clang::NamedDecl *decl, - const ConstString &name, - TypeFromParser type, - bool is_result, - bool is_lvalue); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Add a variable to the struct that needs to - /// be materialized each time the expression runs. - /// - /// @param[in] decl - /// The Clang declaration for the variable. - /// - /// @param[in] name - /// The name of the variable. - /// - /// @param[in] value - /// The LLVM IR value for this variable. - /// - /// @param[in] size - /// The size of the variable in bytes. - /// - /// @param[in] alignment - /// The required alignment of the variable in bytes. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - AddValueToStruct (const clang::NamedDecl *decl, - const ConstString &name, - llvm::Value *value, - size_t size, - lldb::offset_t alignment); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Finalize the struct, laying out the position - /// of each object in it. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - DoStructLayout (); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get general information about the laid-out - /// struct after DoStructLayout() has been called. - /// - /// @param[out] num_elements - /// The number of elements in the struct. - /// - /// @param[out] size - /// The size of the struct, in bytes. - /// - /// @param[out] alignment - /// The alignment of the struct, in bytes. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetStructInfo (uint32_t &num_elements, - size_t &size, - lldb::offset_t &alignment); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get specific information about one field - /// of the laid-out struct after DoStructLayout() has been called. - /// - /// @param[out] decl - /// The parsed Decl for the field, as generated by ClangASTSource - /// on ClangExpressionDeclMap's behalf. In the case of the result - /// value, this will have the name $__lldb_result even if the - /// result value ends up having the name $1. This is an - /// implementation detail of IRForTarget. - /// - /// @param[out] value - /// The IR value for the field (usually a GlobalVariable). In - /// the case of the result value, this will have the correct - /// name ($1, for instance). This is an implementation detail - /// of IRForTarget. - /// - /// @param[out] offset - /// The offset of the field from the beginning of the struct. - /// As long as the struct is aligned according to its required - /// alignment, this offset will align the field correctly. - /// - /// @param[out] name - /// The name of the field as used in materialization. - /// - /// @param[in] index - /// The index of the field about which information is requested. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetStructElement (const clang::NamedDecl *&decl, - llvm::Value *&value, - lldb::offset_t &offset, - ConstString &name, - uint32_t index); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get information about a function given its - /// Decl. - /// - /// @param[in] decl - /// The parsed Decl for the Function, as generated by ClangASTSource - /// on ClangExpressionDeclMap's behalf. - /// - /// @param[out] ptr - /// The absolute address of the function in the target. - /// - /// @return - /// True if the information could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetFunctionInfo (const clang::NamedDecl *decl, - uint64_t &ptr); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get the address of a function given nothing - /// but its name. Some functions are needed but didn't get Decls made - /// during parsing -- specifically, sel_registerName is never called - /// in the generated IR but we need to call it nonetheless. - /// - /// @param[in] name - /// The name of the function. - /// - /// @param[out] ptr - /// The absolute address of the function in the target. - /// - /// @return - /// True if the address could be retrieved; false otherwise. - //------------------------------------------------------------------ - bool - GetFunctionAddress (const ConstString &name, - uint64_t &ptr); - - //------------------------------------------------------------------ - /// [Used by IRForTarget] Get the address of a symbol given nothing - /// but its name. - /// - /// @param[in] target - /// The target to find the symbol in. If not provided, - /// then the current parsing context's Target. - /// - /// @param[in] process - /// The process to use. For Objective-C symbols, the process's - /// Objective-C language runtime may be queried if the process - /// is non-NULL. - /// - /// @param[in] name - /// The name of the symbol. - /// - /// @param[in] module - /// The module to limit the search to. This can be NULL - /// - /// @return - /// Valid load address for the symbol - //------------------------------------------------------------------ - lldb::addr_t - GetSymbolAddress (Target &target, - Process *process, - const ConstString &name, - lldb::SymbolType symbol_type, - Module *module = NULL); - - lldb::addr_t - GetSymbolAddress (const ConstString &name, - lldb::SymbolType symbol_type); - - //------------------------------------------------------------------ - /// [Used by IRInterpreter] Get basic target information. - /// - /// @param[out] byte_order - /// The byte order of the target. - /// - /// @param[out] address_byte_size - /// The size of a pointer in bytes. - /// - /// @return - /// True if the information could be determined; false - /// otherwise. - //------------------------------------------------------------------ - struct TargetInfo - { - lldb::ByteOrder byte_order; - size_t address_byte_size; - - TargetInfo() : - byte_order(lldb::eByteOrderInvalid), - address_byte_size(0) - { - } - - bool IsValid() - { - return (byte_order != lldb::eByteOrderInvalid && - address_byte_size != 0); - } - }; - TargetInfo GetTargetInfo(); - - //------------------------------------------------------------------ - /// [Used by ClangASTSource] Find all entities matching a given name, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls (NameSearchContext &context); - - //------------------------------------------------------------------ - /// Find all entities matching a given name in a given module/namespace, - /// using a NameSearchContext to make Decls for them. - /// - /// @param[in] context - /// The NameSearchContext that can construct Decls for this name. - /// - /// @param[in] module - /// If non-NULL, the module to query. - /// - /// @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. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - void - FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module, - ClangNamespaceDecl &namespace_decl, - unsigned int current_id); -private: - ClangExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. - ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. - bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. - - //---------------------------------------------------------------------- - /// The following values should not live beyond parsing - //---------------------------------------------------------------------- - class ParserVars - { - public: - ParserVars(ClangExpressionDeclMap &decl_map) : - m_decl_map(decl_map) - { - } - - Target * - GetTarget() - { - if (m_exe_ctx.GetTargetPtr()) - return m_exe_ctx.GetTargetPtr(); - else if (m_sym_ctx.target_sp) - m_sym_ctx.target_sp.get(); - return NULL; - } - - ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. - SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. - ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. - bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. - TargetInfo m_target_info; ///< Basic information about the target. - Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. - clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. - private: - ClangExpressionDeclMap &m_decl_map; - DISALLOW_COPY_AND_ASSIGN (ParserVars); - }; - - std::unique_ptr m_parser_vars; - - //---------------------------------------------------------------------- - /// Activate parser-specific variables - //---------------------------------------------------------------------- - void - EnableParserVars() - { - if (!m_parser_vars.get()) - m_parser_vars.reset(new ParserVars(*this)); - } - - //---------------------------------------------------------------------- - /// Deallocate parser-specific variables - //---------------------------------------------------------------------- - void - DisableParserVars() - { - m_parser_vars.reset(); - } - - //---------------------------------------------------------------------- - /// The following values contain layout information for the materialized - /// struct, but are not specific to a single materialization - //---------------------------------------------------------------------- - struct StructVars { - StructVars() : - m_struct_alignment(0), - m_struct_size(0), - m_struct_laid_out(false), - m_result_name(), - m_object_pointer_type(NULL, NULL) - { - } - - lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. - size_t m_struct_size; ///< The size of the struct in bytes. - bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). - ConstString m_result_name; ///< The name of the result variable ($1, for example) - TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists - }; - - std::unique_ptr m_struct_vars; - - //---------------------------------------------------------------------- - /// Activate struct variables - //---------------------------------------------------------------------- - void - EnableStructVars() - { - if (!m_struct_vars.get()) - m_struct_vars.reset(new struct StructVars); - } - - //---------------------------------------------------------------------- - /// Deallocate struct variables - //---------------------------------------------------------------------- - void - DisableStructVars() - { - m_struct_vars.reset(); - } - - //---------------------------------------------------------------------- - /// Get this parser's ID for use in extracting parser- and JIT-specific - /// data from persistent variables. - //---------------------------------------------------------------------- - uint64_t - GetParserID() - { - return (uint64_t)this; - } - - //------------------------------------------------------------------ - /// Given a target, find a data symbol that has the given name. - /// - /// @param[in] target - /// The target to use as the basis for the search. - /// - /// @param[in] name - /// The name as a plain C string. - /// - /// @param[in] module - /// The module to limit the search to. This can be NULL - /// - /// @return - /// The LLDB Symbol found, or NULL if none was found. - //------------------------------------------------------------------ - const Symbol * - FindGlobalDataSymbol (Target &target, - const ConstString &name, - Module *module = NULL); - - //------------------------------------------------------------------ - /// Given a target, find a variable that matches the given name and - /// type. - /// - /// @param[in] target - /// The target to use as a basis for finding the variable. - /// - /// @param[in] module - /// If non-NULL, the module to search. - /// - /// @param[in] name - /// The name as a plain C string. - /// - /// @param[in] namespace_decl - /// If non-NULL and module is non-NULL, the parent namespace. - /// - /// @param[in] type - /// The required type for the variable. This function may be called - /// during parsing, in which case we don't know its type; hence the - /// default. - /// - /// @return - /// The LLDB Variable found, or NULL if none was found. - //------------------------------------------------------------------ - lldb::VariableSP - FindGlobalVariable (Target &target, - lldb::ModuleSP &module, - const ConstString &name, - ClangNamespaceDecl *namespace_decl, - TypeFromUser *type = NULL); - - //------------------------------------------------------------------ - /// Get the value of a variable in a given execution context and return - /// the associated Types if needed. - /// - /// @param[in] var - /// The variable to evaluate. - /// - /// @param[out] var_location - /// The variable location value to fill in - /// - /// @param[out] found_type - /// The type of the found value, as it was found in the user process. - /// This is only useful when the variable is being inspected on behalf - /// of the parser, hence the default. - /// - /// @param[out] parser_type - /// The type of the found value, as it was copied into the parser's - /// AST context. This is only useful when the variable is being - /// inspected on behalf of the parser, hence the default. - /// - /// @param[in] decl - /// The Decl to be looked up. - /// - /// @return - /// Return true if the value was successfully filled in. - //------------------------------------------------------------------ - bool - GetVariableValue (lldb::VariableSP &var, - lldb_private::Value &var_location, - TypeFromUser *found_type = NULL, - TypeFromParser *parser_type = NULL); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given LLDB - /// Variable, and put it in the Tuple list. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] var - /// The LLDB Variable that needs a Decl. - /// - /// @param[in] valobj - /// The LLDB ValueObject for that variable. - //------------------------------------------------------------------ - void - AddOneVariable (NameSearchContext &context, - lldb::VariableSP var, - lldb::ValueObjectSP valobj, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// persistent variable, and put it in the list of found entities. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] pvar - /// The persistent variable that needs a Decl. - /// - /// @param[in] current_id - /// The ID of the current invocation of FindExternalVisibleDecls - /// for logging purposes. - //------------------------------------------------------------------ - void - AddOneVariable (NameSearchContext &context, - lldb::ClangExpressionVariableSP &pvar_sp, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given LLDB - /// symbol (treated as a variable), and put it in the list of found - /// entities. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] var - /// The LLDB Variable that needs a Decl. - //------------------------------------------------------------------ - void - AddOneGenericVariable (NameSearchContext &context, - const Symbol &symbol, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// function. (Functions are not placed in the Tuple list.) Can - /// handle both fully typed functions and generic functions. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] fun - /// The Function that needs to be created. If non-NULL, this is - /// a fully-typed function. - /// - /// @param[in] sym - /// The Symbol that corresponds to a function that needs to be - /// created with generic type (unitptr_t foo(...)). - //------------------------------------------------------------------ - void - AddOneFunction (NameSearchContext &context, - Function *fun, - Symbol *sym, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// register. - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] reg_info - /// The information corresponding to that register. - //------------------------------------------------------------------ - void - AddOneRegister (NameSearchContext &context, - const RegisterInfo *reg_info, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// type. (Types are not placed in the Tuple list.) - /// - /// @param[in] context - /// The NameSearchContext to use when constructing the Decl. - /// - /// @param[in] type - /// The type that needs to be created. - //------------------------------------------------------------------ - void - AddOneType (NameSearchContext &context, - TypeFromUser &type, - unsigned int current_id); - - //------------------------------------------------------------------ - /// Copy a C++ class type into the parser's AST context and add a - /// member function declaration to it for the expression. - /// - /// @param[in] type - /// The type that needs to be created. - //------------------------------------------------------------------ - - TypeFromParser - CopyClassType(TypeFromUser &type, - unsigned int current_id); -}; - -} // namespace lldb_private - -#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/include/lldb/Expression/ClangExpressionParser.h b/include/lldb/Expression/ClangExpressionParser.h deleted file mode 100644 index 21a27a489bcd..000000000000 --- a/include/lldb/Expression/ClangExpressionParser.h +++ /dev/null @@ -1,156 +0,0 @@ -//===-- ClangExpressionParser.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_ClangExpressionParser_h_ -#define liblldb_ClangExpressionParser_h_ - -#include "lldb/lldb-public.h" -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Core/Error.h" -#include "lldb/Expression/IRForTarget.h" - -#include -#include - -namespace lldb_private -{ - -class IRExecutionUnit; - -//---------------------------------------------------------------------- -/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" -/// @brief Encapsulates an instance of Clang that can parse expressions. -/// -/// ClangExpressionParser is responsible for preparing an instance of -/// ClangExpression for execution. ClangExpressionParser uses ClangExpression -/// as a glorified parameter list, performing the required parsing and -/// conversion to formats (DWARF bytecode, or JIT compiled machine code) -/// that can be executed. -//---------------------------------------------------------------------- -class ClangExpressionParser -{ -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// Initializes class variables. - /// - /// @param[in] exe_scope, - /// If non-NULL, an execution context scope that can help to - /// correctly create an expression with a valid process for - /// optional tuning Objective-C runtime support. Can be NULL. - /// - /// @param[in] expr - /// The expression to be parsed. - //------------------------------------------------------------------ - ClangExpressionParser (ExecutionContextScope *exe_scope, - ClangExpression &expr, - bool generate_debug_info); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~ClangExpressionParser (); - - //------------------------------------------------------------------ - /// Parse a single expression and convert it to IR using Clang. Don't - /// wrap the expression in anything at all. - /// - /// @param[in] stream - /// The stream to print errors to. - /// - /// @return - /// The number of errors encountered during parsing. 0 means - /// success. - //------------------------------------------------------------------ - unsigned - Parse (Stream &stream); - - //------------------------------------------------------------------ - /// Ready an already-parsed expression for execution, possibly - /// evaluating it statically. - /// - /// @param[out] func_addr - /// The address to which the function has been written. - /// - /// @param[out] func_end - /// The end of the function's allocated memory region. (func_addr - /// and func_end do not delimit an allocated region; the allocated - /// region may begin before func_addr.) - /// - /// @param[in] execution_unit_sp - /// After parsing, ownership of the execution unit for - /// for the expression is handed to this shared pointer. - /// - /// @param[in] exe_ctx - /// The execution context to write the function into. - /// - /// @param[out] evaluated_statically - /// Set to true if the expression could be interpreted statically; - /// untouched otherwise. - /// - /// @param[out] const_result - /// If the result of the expression is constant, and the - /// expression has no side effects, this is set to the result of the - /// expression. - /// - /// @param[in] execution_policy - /// Determines whether the expression must be JIT-compiled, must be - /// evaluated statically, or whether this decision may be made - /// opportunistically. - /// - /// @return - /// An error code indicating the success or failure of the operation. - /// Test with Success(). - //------------------------------------------------------------------ - Error - PrepareForExecution (lldb::addr_t &func_addr, - lldb::addr_t &func_end, - std::shared_ptr &execution_unit_sp, - ExecutionContext &exe_ctx, - bool &can_interpret, - lldb_private::ExecutionPolicy execution_policy); - - //------------------------------------------------------------------ - /// Disassemble the machine code for a JITted function from the target - /// process's memory and print the result to a stream. - /// - /// @param[in] stream - /// The stream to print disassembly to. - /// - /// @param[in] exc_context - /// The execution context to get the machine code from. - /// - /// @return - /// The error generated. If .Success() is true, disassembly succeeded. - //------------------------------------------------------------------ - Error - DisassembleFunction (Stream &stream, - ExecutionContext &exe_ctx); - - bool - GetGenerateDebugInfo () const; - -private: - ClangExpression & m_expr; ///< The expression to be parsed - std::unique_ptr m_llvm_context; ///< The LLVM context to generate IR into - std::unique_ptr m_file_manager; ///< The Clang file manager object used by the compiler - std::unique_ptr m_compiler; ///< The Clang compiler used to parse expressions into IR - std::unique_ptr m_builtin_context; ///< Context for Clang built-ins - std::unique_ptr m_selector_table; ///< Selector table for Objective-C methods - std::unique_ptr m_code_generator; ///< The Clang object that generates IR - - class LLDBPreprocessorCallbacks; - LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports -}; - -} - -#endif // liblldb_ClangExpressionParser_h_ diff --git a/include/lldb/Expression/ClangExpressionVariable.h b/include/lldb/Expression/ClangExpressionVariable.h deleted file mode 100644 index 6c210106d51e..000000000000 --- a/include/lldb/Expression/ClangExpressionVariable.h +++ /dev/null @@ -1,456 +0,0 @@ -//===-- ClangExpressionVariable.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_ClangExpressionVariable_h_ -#define liblldb_ClangExpressionVariable_h_ - -// C Includes -#include -#include -#include - -// C++ Includes -#include -#include -#include - -// Other libraries and framework includes -// Project includes -#include "lldb/lldb-public.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Value.h" -#include "lldb/Symbol/TaggedASTType.h" - -namespace llvm { - class Value; -} - -namespace lldb_private { - -class ClangExpressionVariableList; -class ValueObjectConstResult; - -//---------------------------------------------------------------------- -/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" -/// @brief Encapsulates one variable for the expression parser. -/// -/// The expression parser uses variables in three different contexts: -/// -/// First, it stores persistent variables along with the process for use -/// in expressions. These persistent variables contain their own data -/// and are typed. -/// -/// Second, in an interpreted expression, it stores the local variables -/// for the expression along with the expression. These variables -/// contain their own data and are typed. -/// -/// Third, in a JIT-compiled expression, it stores the variables that -/// the expression needs to have materialized and dematerialized at each -/// execution. These do not contain their own data but are named and -/// typed. -/// -/// This class supports all of these use cases using simple type -/// polymorphism, and provides necessary support methods. Its interface -/// is RTTI-neutral. -//---------------------------------------------------------------------- -class ClangExpressionVariable -{ -public: - ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); - - ClangExpressionVariable (ExecutionContextScope *exe_scope, - Value &value, - const ConstString &name, - uint16_t flags = EVNone); - - ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); - - //---------------------------------------------------------------------- - /// If the variable contains its own data, make a Value point at it. - /// If \a exe_ctx in not NULL, the value will be resolved in with - /// that execution context. - /// - /// @param[in] value - /// The value to point at the data. - /// - /// @param[in] exe_ctx - /// The execution context to use to resolve \a value. - /// - /// @return - /// True on success; false otherwise (in particular, if this variable - /// does not contain its own data). - //---------------------------------------------------------------------- - bool - PointValueAtData(Value &value, ExecutionContext *exe_ctx); - - lldb::ValueObjectSP - GetValueObject(); - - //---------------------------------------------------------------------- - /// The following values should not live beyond parsing - //---------------------------------------------------------------------- - class ParserVars - { - public: - - ParserVars() : - m_parser_type(), - m_named_decl (NULL), - m_llvm_value (NULL), - m_lldb_value (), - m_lldb_var (), - m_lldb_sym (NULL) - { - } - - TypeFromParser m_parser_type; ///< The type of the variable according to the parser - const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable - llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue - lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable - lldb::VariableSP m_lldb_var; ///< The original variable for this variable - const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol - }; - -private: - typedef std::map ParserVarMap; - ParserVarMap m_parser_vars; - -public: - //---------------------------------------------------------------------- - /// Make this variable usable by the parser by allocating space for - /// parser-specific variables - //---------------------------------------------------------------------- - void - EnableParserVars(uint64_t parser_id) - { - m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); - } - - //---------------------------------------------------------------------- - /// Deallocate parser-specific variables - //---------------------------------------------------------------------- - void - DisableParserVars(uint64_t parser_id) - { - m_parser_vars.erase(parser_id); - } - - //---------------------------------------------------------------------- - /// Access parser-specific variables - //---------------------------------------------------------------------- - ParserVars * - GetParserVars(uint64_t parser_id) - { - ParserVarMap::iterator i = m_parser_vars.find(parser_id); - - if (i == m_parser_vars.end()) - return NULL; - else - return &i->second; - } - - //---------------------------------------------------------------------- - /// The following values are valid if the variable is used by JIT code - //---------------------------------------------------------------------- - struct JITVars { - JITVars () : - m_alignment (0), - m_size (0), - m_offset (0) - { - } - - lldb::offset_t m_alignment; ///< The required alignment of the variable, in bytes - size_t m_size; ///< The space required for the variable, in bytes - lldb::offset_t m_offset; ///< The offset of the variable in the struct, in bytes - }; - -private: - typedef std::map JITVarMap; - JITVarMap m_jit_vars; - -public: - //---------------------------------------------------------------------- - /// Make this variable usable for materializing for the JIT by allocating - /// space for JIT-specific variables - //---------------------------------------------------------------------- - void - EnableJITVars(uint64_t parser_id) - { - m_jit_vars.insert(std::make_pair(parser_id, JITVars())); - } - - //---------------------------------------------------------------------- - /// Deallocate JIT-specific variables - //---------------------------------------------------------------------- - void - DisableJITVars(uint64_t parser_id) - { - m_jit_vars.erase(parser_id); - } - - JITVars *GetJITVars(uint64_t parser_id) - { - JITVarMap::iterator i = m_jit_vars.find(parser_id); - - if (i == m_jit_vars.end()) - return NULL; - else - return &i->second; - } - - //---------------------------------------------------------------------- - /// Return the variable's size in bytes - //---------------------------------------------------------------------- - size_t - GetByteSize (); - - const ConstString & - GetName(); - - RegisterInfo * - GetRegisterInfo(); - - void - SetRegisterInfo (const RegisterInfo *reg_info); - - ClangASTType - GetClangType (); - - void - SetClangType (const ClangASTType &clang_type); - - TypeFromUser - GetTypeFromUser (); - - uint8_t * - GetValueBytes (); - - void - SetName (const ConstString &name); - - void - ValueUpdated (); - - // this function is used to copy the address-of m_live_sp into m_frozen_sp - // this is necessary because the results of certain cast and pointer-arithmetic - // operations (such as those described in bugzilla issues 11588 and 11618) generate - // frozen objects that do not have a valid address-of, which can be troublesome when - // using synthetic children providers. Transferring the address-of the live object - // solves these issues and provides the expected user-level behavior - void - TransferAddress (bool force = false); - - typedef std::shared_ptr ValueObjectConstResultSP; - - //---------------------------------------------------------------------- - /// Members - //---------------------------------------------------------------------- - enum Flags - { - EVNone = 0, - EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process - EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program - EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process - EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results) - EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization - EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it - EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location - EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete - EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or some other entity. - }; - - typedef uint16_t FlagType; - - FlagType m_flags; // takes elements of Flags - - lldb::ValueObjectSP m_frozen_sp; - lldb::ValueObjectSP m_live_sp; - - DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); -}; - -//---------------------------------------------------------------------- -/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" -/// @brief A list of variable references. -/// -/// This class stores variables internally, acting as the permanent store. -//---------------------------------------------------------------------- -class ClangExpressionVariableList -{ -public: - //---------------------------------------------------------------------- - /// Implementation of methods in ClangExpressionVariableListBase - //---------------------------------------------------------------------- - size_t - GetSize() - { - return m_variables.size(); - } - - lldb::ClangExpressionVariableSP - GetVariableAtIndex(size_t index) - { - lldb::ClangExpressionVariableSP var_sp; - if (index < m_variables.size()) - var_sp = m_variables[index]; - return var_sp; - } - - size_t - AddVariable (const lldb::ClangExpressionVariableSP &var_sp) - { - m_variables.push_back(var_sp); - return m_variables.size() - 1; - } - - bool - ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp) - { - const size_t size = m_variables.size(); - for (size_t index = 0; index < size; ++index) - { - if (m_variables[index].get() == var_sp.get()) - return true; - } - return false; - } - - //---------------------------------------------------------------------- - /// Finds a variable by name in the list. - /// - /// @param[in] name - /// The name of the requested variable. - /// - /// @return - /// The variable requested, or NULL if that variable is not in the list. - //---------------------------------------------------------------------- - lldb::ClangExpressionVariableSP - GetVariable (const ConstString &name) - { - lldb::ClangExpressionVariableSP var_sp; - for (size_t index = 0, size = GetSize(); index < size; ++index) - { - var_sp = GetVariableAtIndex(index); - if (var_sp->GetName() == name) - return var_sp; - } - var_sp.reset(); - return var_sp; - } - - lldb::ClangExpressionVariableSP - GetVariable (const char *name) - { - lldb::ClangExpressionVariableSP var_sp; - if (name && name[0]) - { - for (size_t index = 0, size = GetSize(); index < size; ++index) - { - var_sp = GetVariableAtIndex(index); - const char *var_name_cstr = var_sp->GetName().GetCString(); - if (!var_name_cstr || !name) - continue; - if (::strcmp (var_name_cstr, name) == 0) - return var_sp; - } - var_sp.reset(); - } - return var_sp; - } - - //---------------------------------------------------------------------- - /// Finds a variable by NamedDecl in the list. - /// - /// @param[in] name - /// The name of the requested variable. - /// - /// @return - /// The variable requested, or NULL if that variable is not in the list. - //---------------------------------------------------------------------- - lldb::ClangExpressionVariableSP - GetVariable (const clang::NamedDecl *decl, uint64_t parser_id) - { - lldb::ClangExpressionVariableSP var_sp; - for (size_t index = 0, size = GetSize(); index < size; ++index) - { - var_sp = GetVariableAtIndex(index); - - ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(parser_id); - - if (parser_vars && parser_vars->m_named_decl == decl) - return var_sp; - } - var_sp.reset(); - return var_sp; - } - - //---------------------------------------------------------------------- - /// Create a new variable in the list and return its index - //---------------------------------------------------------------------- - lldb::ClangExpressionVariableSP - CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) - { - lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size)); - m_variables.push_back(var_sp); - return var_sp; - } - - lldb::ClangExpressionVariableSP - CreateVariable(const lldb::ValueObjectSP &valobj_sp) - { - lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp)); - m_variables.push_back(var_sp); - return var_sp; - } - - lldb::ClangExpressionVariableSP - CreateVariable (ExecutionContextScope *exe_scope, - const ConstString &name, - const TypeFromUser& user_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size) - { - lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size)); - var_sp->SetName (name); - var_sp->SetClangType (user_type); - m_variables.push_back(var_sp); - return var_sp; - } - - void - RemoveVariable (lldb::ClangExpressionVariableSP var_sp) - { - for (std::vector::iterator vi = m_variables.begin(), ve = m_variables.end(); - vi != ve; - ++vi) - { - if (vi->get() == var_sp.get()) - { - m_variables.erase(vi); - return; - } - } - } - - void - Clear() - { - m_variables.clear(); - } - -private: - std::vector m_variables; -}; - - -} // namespace lldb_private - -#endif // liblldb_ClangExpressionVariable_h_ diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h deleted file mode 100644 index cf7e2592021f..000000000000 --- a/include/lldb/Expression/ClangFunction.h +++ /dev/null @@ -1,451 +0,0 @@ -//===-- ClangFunction.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_ClangFunction_h_ -#define lldb_ClangFunction_h_ - -// C Includes -// C++ Includes -#include -#include -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ClangForward.h" -#include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Value.h" -#include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Target/Process.h" - -namespace lldb_private -{ - -class ASTStructExtractor; -class ClangExpressionParser; - -//---------------------------------------------------------------------- -/// @class ClangFunction ClangFunction.h "lldb/Expression/ClangFunction.h" -/// @brief Encapsulates a function that can be called. -/// -/// A given ClangFunction object can handle a single function signature. -/// Once constructed, it can set up any number of concurrent calls to -/// functions with that signature. -/// -/// It performs the call by synthesizing a structure that contains the pointer -/// to the function and the arguments that should be passed to that function, -/// and producing a special-purpose JIT-compiled function that accepts a void* -/// pointing to this struct as its only argument and calls the function in the -/// struct with the written arguments. This method lets Clang handle the -/// vagaries of function calling conventions. -/// -/// The simplest use of the ClangFunction is to construct it with a -/// function representative of the signature you want to use, then call -/// ExecuteFunction(ExecutionContext &, Stream &, Value &). -/// -/// If you need to reuse the arguments for several calls, you can call -/// InsertFunction() followed by WriteFunctionArguments(), which will return -/// the location of the args struct for the wrapper function in args_addr_ref. -/// -/// If you need to call the function on the thread plan stack, you can also -/// call InsertFunction() followed by GetThreadPlanToCallFunction(). -/// -/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed -/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated -/// and its address returned in that variable. -/// -/// Any of the methods that take arg_addr_ptr can be passed NULL, and the -/// argument space will be managed for you. -//---------------------------------------------------------------------- -class ClangFunction : public ClangExpression -{ - friend class ASTStructExtractor; -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] exe_scope - /// An execution context scope that gets us at least a target and - /// process. - /// - /// @param[in] function_ptr - /// The default function to be called. Can be overridden using - /// WriteFunctionArguments(). - /// - /// @param[in] ast_context - /// The AST context to evaluate argument types in. - /// - /// @param[in] arg_value_list - /// The default values to use when calling this function. Can - /// be overridden using WriteFunctionArguments(). - //------------------------------------------------------------------ - ClangFunction (ExecutionContextScope &exe_scope, - Function &function_ptr, - ClangASTContext *ast_context, - const ValueList &arg_value_list, - const char *name); - - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] exe_scope - /// An execution context scope that gets us at least a target and - /// process. - /// - /// @param[in] ast_context - /// The AST context to evaluate argument types in. - /// - /// @param[in] return_qualtype - /// An opaque Clang QualType for the function result. Should be - /// defined in ast_context. - /// - /// @param[in] function_address - /// The address of the function to call. - /// - /// @param[in] arg_value_list - /// The default values to use when calling this function. Can - /// be overridden using WriteFunctionArguments(). - //------------------------------------------------------------------ - ClangFunction (ExecutionContextScope &exe_scope, - const ClangASTType &return_type, - const Address& function_address, - const ValueList &arg_value_list, - const char *name); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual - ~ClangFunction(); - - //------------------------------------------------------------------ - /// Compile the wrapper function - /// - /// @param[in] errors - /// The stream to print parser errors to. - /// - /// @return - /// The number of errors. - //------------------------------------------------------------------ - unsigned - CompileFunction (Stream &errors); - - //------------------------------------------------------------------ - /// Insert the default function wrapper and its default argument struct - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in,out] args_addr_ref - /// The address of the structure to write the arguments into. May - /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated - /// and args_addr_ref is pointed to it. - /// - /// @param[in] errors - /// The stream to write errors to. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - InsertFunction (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Stream &errors); - - //------------------------------------------------------------------ - /// Insert the default function wrapper (using the JIT) - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in] errors - /// The stream to write errors to. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool WriteFunctionWrapper (ExecutionContext &exe_ctx, - Stream &errors); - - //------------------------------------------------------------------ - /// Insert the default function argument struct - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in,out] args_addr_ref - /// The address of the structure to write the arguments into. May - /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated - /// and args_addr_ref is pointed to it. - /// - /// @param[in] errors - /// The stream to write errors to. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Stream &errors); - - //------------------------------------------------------------------ - /// Insert an argument struct with a non-default function address and - /// non-default argument values - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in,out] args_addr_ref - /// The address of the structure to write the arguments into. May - /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated - /// and args_addr_ref is pointed to it. - /// - /// @param[in] function_address - /// The address of the function to call. - /// - /// @param[in] arg_values - /// The values of the function's arguments. - /// - /// @param[in] errors - /// The stream to write errors to. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Address function_address, - ValueList &arg_values, - Stream &errors); - - //------------------------------------------------------------------ - /// Run the function this ClangFunction was created with. - /// - /// This is the full version. - /// - /// @param[in] exe_ctx - /// The thread & process in which this function will run. - /// - /// @param[in] args_addr_ptr - /// If NULL, the function will take care of allocating & deallocating the wrapper - /// args structure. Otherwise, if set to LLDB_INVALID_ADDRESS, a new structure - /// will be allocated, filled and the address returned to you. You are responsible - /// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS, - /// this should point to an already allocated structure with the values already written. - /// - /// @param[in] errors - /// Errors will be written here if there are any. - /// - /// @param[in] options - /// The options for this expression execution. - /// - /// @param[out] results - /// The result value will be put here after running the function. - /// - /// @return - /// Returns one of the ExpressionResults enum indicating function call status. - //------------------------------------------------------------------ - lldb::ExpressionResults - ExecuteFunction(ExecutionContext &exe_ctx, - lldb::addr_t *args_addr_ptr, - const EvaluateExpressionOptions &options, - Stream &errors, - Value &results); - - //------------------------------------------------------------------ - /// Get a thread plan to run the function this ClangFunction was created with. - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in] func_addr - /// The address of the function in the target process. - /// - /// @param[in] args_addr - /// The address of the argument struct. - /// - /// @param[in] errors - /// The stream to write errors to. - /// - /// @param[in] stop_others - /// True if other threads should pause during execution. - /// - /// @param[in] unwind_on_error - /// True if the thread plan may simply be discarded if an error occurs. - /// - /// @return - /// A ThreadPlan shared pointer for executing the function. - //------------------------------------------------------------------ - lldb::ThreadPlanSP - GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, - const EvaluateExpressionOptions &options, - Stream &errors); - - //------------------------------------------------------------------ - /// Get the result of the function from its struct - /// - /// @param[in] exe_ctx - /// The execution context to retrieve the result from. - /// - /// @param[in] args_addr - /// The address of the argument struct. - /// - /// @param[out] ret_value - /// The value returned by the function. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool FetchFunctionResults (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, - Value &ret_value); - - //------------------------------------------------------------------ - /// Deallocate the arguments structure - /// - /// @param[in] exe_ctx - /// The execution context to insert the function and its arguments - /// into. - /// - /// @param[in] args_addr - /// The address of the argument struct. - //------------------------------------------------------------------ - void DeallocateFunctionResults (ExecutionContext &exe_ctx, - lldb::addr_t args_addr); - - //------------------------------------------------------------------ - /// Interface for ClangExpression - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Return the string that the parser should parse. Must be a full - /// translation unit. - //------------------------------------------------------------------ - const char * - Text () - { - return m_wrapper_function_text.c_str(); - } - - //------------------------------------------------------------------ - /// Return the function name that should be used for executing the - /// expression. Text() should contain the definition of this - /// function. - //------------------------------------------------------------------ - const char * - FunctionName () - { - return m_wrapper_function_name.c_str(); - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap () - { - return NULL; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when registering - /// local variables. May be NULL if the Expression doesn't care. - //------------------------------------------------------------------ - ClangExpressionVariableList * - LocalVariables () - { - return NULL; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer (clang::ASTConsumer *passthrough); - - //------------------------------------------------------------------ - /// Return true if validation code should be inserted into the - /// expression. - //------------------------------------------------------------------ - bool - NeedsValidation () - { - return false; - } - - //------------------------------------------------------------------ - /// Return true if external variables in the expression should be - /// resolved. - //------------------------------------------------------------------ - bool - NeedsVariableResolution () - { - return false; - } - - ValueList - GetArgumentValues () const - { - return m_arg_values; - } -private: - //------------------------------------------------------------------ - // For ClangFunction only - //------------------------------------------------------------------ - - // Note: the parser needs to be destructed before the execution unit, so - // declare the execution unit first. - std::shared_ptr m_execution_unit_sp; - std::unique_ptr m_parser; ///< The parser responsible for compiling the function. - lldb::ModuleWP m_jit_module_wp; - std::string m_name; ///< The name of this clang function - for debugging purposes. - - Function *m_function_ptr; ///< The function we're going to call. May be NULL if we don't have debug info for the function. - Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type. - ClangASTType m_function_return_type; ///< The opaque clang qual type for the function return type. - - std::string m_wrapper_function_name; ///< The name of the wrapper function. - std::string m_wrapper_function_text; ///< The contents of the wrapper function. - std::string m_wrapper_struct_name; ///< The name of the struct that contains the target function address, arguments, and result. - std::list m_wrapper_args_addrs; ///< The addresses of the arguments to the wrapper function. - - std::unique_ptr m_struct_extractor; ///< The class that generates the argument struct below. - - bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below. - - //------------------------------------------------------------------ - /// These values are populated by the ASTStructExtractor - size_t m_struct_size; ///< The size of the argument struct, in bytes. - std::vector m_member_offsets; ///< The offset of each member in the struct, in bytes. - uint64_t m_return_size; ///< The size of the result variable, in bytes. - uint64_t m_return_offset; ///< The offset of the result variable in the struct, in bytes. - //------------------------------------------------------------------ - - ValueList m_arg_values; ///< The default values of the arguments. - - bool m_compiled; ///< True if the wrapper function has already been parsed. - bool m_JITted; ///< True if the wrapper function has already been JIT-compiled. -}; - -} // Namespace lldb_private - -#endif // lldb_ClangFunction_h_ diff --git a/include/lldb/Expression/ClangModulesDeclVendor.h b/include/lldb/Expression/ClangModulesDeclVendor.h deleted file mode 100644 index a8297c8fa331..000000000000 --- a/include/lldb/Expression/ClangModulesDeclVendor.h +++ /dev/null @@ -1,129 +0,0 @@ -//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef _liblldb_ClangModulesDeclVendor_ -#define _liblldb_ClangModulesDeclVendor_ - -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Symbol/DeclVendor.h" -#include "lldb/Target/Platform.h" - -#include -#include - -namespace lldb_private -{ - -class ClangModulesDeclVendor : public DeclVendor -{ -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ClangModulesDeclVendor(); - - virtual - ~ClangModulesDeclVendor(); - - static ClangModulesDeclVendor * - Create(Target &target); - - typedef std::vector ModulePath; - typedef uintptr_t ModuleID; - typedef std::vector ModuleVector; - - //------------------------------------------------------------------ - /// Add a module to the list of modules to search. - /// - /// @param[in] path - /// The path to the exact module to be loaded. E.g., if the desired - /// module is std.io, then this should be { "std", "io" }. - /// - /// @param[in] exported_modules - /// If non-NULL, a pointer to a vector to populate with the ID of every - /// module that is re-exported by the specified module. - /// - /// @param[in] error_stream - /// A stream to populate with the output of the Clang parser when - /// it tries to load the module. - /// - /// @return - /// True if the module could be loaded; false if not. If the - /// compiler encountered a fatal error during a previous module - /// load, then this will always return false for this ModuleImporter. - //------------------------------------------------------------------ - virtual bool - AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) = 0; - - //------------------------------------------------------------------ - /// Add all modules referred to in a given compilation unit to the list - /// of modules to search. - /// - /// @param[in] cu - /// The compilation unit to scan for imported modules. - /// - /// @param[in] exported_modules - /// A vector to populate with the ID of each module loaded (directly - /// and via re-exports) in this way. - /// - /// @param[in] error_stream - /// A stream to populate with the output of the Clang parser when - /// it tries to load the modules. - /// - /// @return - /// True if all modules referred to by the compilation unit could be - /// loaded; false if one could not be loaded. If the compiler - /// encountered a fatal error during a previous module - /// load, then this will always return false for this ModuleImporter. - //------------------------------------------------------------------ - virtual bool - AddModulesForCompileUnit(CompileUnit &cu, - ModuleVector &exported_modules, - Stream &error_stream) = 0; - - //------------------------------------------------------------------ - /// Enumerate all the macros that are defined by a given set of modules - /// that are already imported. - /// - /// @param[in] modules - /// The unique IDs for all modules to query. Later modules have higher - /// priority, just as if you @imported them in that order. This matters - /// if module A #defines a macro and module B #undefs it. - /// - /// @param[in] handler - /// A function to call with the text of each #define (including the - /// #define directive). #undef directives are not included; we simply - /// elide any corresponding #define. If this function returns true, - /// we stop the iteration immediately. - //------------------------------------------------------------------ - virtual void - ForEachMacro(const ModuleVector &modules, - std::function handler) = 0; - - //------------------------------------------------------------------ - /// Query whether Clang supports modules for a particular language. - /// LLDB uses this to decide whether to try to find the modules loaded - /// by a gaiven compile unit. - /// - /// @param[in] language - /// The language to query for. - /// - /// @return - /// True if Clang has modules for the given language. - //------------------------------------------------------------------ - static bool - LanguageSupportsClangModules (lldb::LanguageType language); - -}; - -} -#endif /* defined(_lldb_ClangModulesDeclVendor_) */ diff --git a/include/lldb/Expression/ClangPersistentVariables.h b/include/lldb/Expression/ClangPersistentVariables.h deleted file mode 100644 index 247f87fae41b..000000000000 --- a/include/lldb/Expression/ClangPersistentVariables.h +++ /dev/null @@ -1,91 +0,0 @@ -//===-- ClangPersistentVariables.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_ClangPersistentVariables_h_ -#define liblldb_ClangPersistentVariables_h_ - -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" - -#include "llvm/ADT/DenseMap.h" - -namespace lldb_private -{ - -//---------------------------------------------------------------------- -/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" -/// @brief Manages persistent values that need to be preserved between expression invocations. -/// -/// A list of variables that can be accessed and updated by any expression. See -/// ClangPersistentVariable for more discussion. Also provides an increasing, -/// 0-based counter for naming result variables. -//---------------------------------------------------------------------- -class ClangPersistentVariables : public ClangExpressionVariableList -{ -public: - - //---------------------------------------------------------------------- - /// Constructor - //---------------------------------------------------------------------- - ClangPersistentVariables (); - - lldb::ClangExpressionVariableSP - CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp); - - lldb::ClangExpressionVariableSP - CreatePersistentVariable (ExecutionContextScope *exe_scope, - const ConstString &name, - const TypeFromUser& user_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size); - - //---------------------------------------------------------------------- - /// Return the next entry in the sequence of strings "$0", "$1", ... for - /// use naming persistent expression convenience variables. - /// - /// @return - /// A string that contains the next persistent variable name. - //---------------------------------------------------------------------- - ConstString - GetNextPersistentVariableName (); - - void - RemovePersistentVariable (lldb::ClangExpressionVariableSP variable); - - void - RegisterPersistentType (const ConstString &name, - clang::TypeDecl *tag_decl); - - clang::TypeDecl * - GetPersistentType (const ConstString &name); - - void - AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) - { - m_hand_loaded_clang_modules.push_back(module); - } - - const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() - { - return m_hand_loaded_clang_modules; - } - -private: - uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). - - typedef llvm::DenseMap PersistentTypeMap; - PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. - - ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- - ///< priority source for macros. -}; - -} - -#endif diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h deleted file mode 100644 index a549f5e8a547..000000000000 --- a/include/lldb/Expression/ClangUserExpression.h +++ /dev/null @@ -1,365 +0,0 @@ -//===-- ClangUserExpression.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_ClangUserExpression_h_ -#define liblldb_ClangUserExpression_h_ - -// C Includes -// C++ Includes -#include -#include -#include - -// Other libraries and framework includes -// Project includes - -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/Address.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/IRForTarget.h" -#include "lldb/Expression/Materializer.h" -#include "lldb/Symbol/TaggedASTType.h" -#include "lldb/Target/ExecutionContext.h" - -namespace lldb_private -{ - -//---------------------------------------------------------------------- -/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" -/// @brief Encapsulates a single expression for use with Clang -/// -/// LLDB uses expressions for various purposes, notably to call functions -/// and as a backend for the expr command. ClangUserExpression encapsulates -/// the objects needed to parse and interpret or JIT an expression. It -/// uses the Clang parser to produce LLVM IR from the expression. -//---------------------------------------------------------------------- -class ClangUserExpression : public ClangExpression -{ -public: - - enum { kDefaultTimeout = 500000u }; - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] expr - /// The expression to parse. - /// - /// @param[in] expr_prefix - /// If non-NULL, a C string containing translation-unit level - /// definitions to be included when the expression is parsed. - /// - /// @param[in] language - /// If not eLanguageTypeUnknown, a language to use when parsing - /// the expression. Currently restricted to those languages - /// supported by Clang. - /// - /// @param[in] desired_type - /// If not eResultTypeAny, the type to use for the expression - /// result. - //------------------------------------------------------------------ - ClangUserExpression (const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual - ~ClangUserExpression (); - - //------------------------------------------------------------------ - /// Parse the expression - /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. - /// - /// @param[in] exe_ctx - /// The execution context to use when looking up entities that - /// are needed for parsing (locations of functions, types of - /// variables, persistent variables, etc.) - /// - /// @param[in] execution_policy - /// Determines whether interpretation is possible or mandatory. - /// - /// @param[in] keep_result_in_memory - /// True if the resulting persistent variable should reside in - /// target memory, if applicable. - /// - /// @return - /// True on success (no errors); false otherwise. - //------------------------------------------------------------------ - bool - Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info); - - bool - CanInterpret () - { - return m_can_interpret; - } - - bool - MatchesContext (ExecutionContext &exe_ctx); - - //------------------------------------------------------------------ - /// Execute the parsed expression - /// - /// @param[in] error_stream - /// A stream to print errors to. - /// - /// @param[in] exe_ctx - /// The execution context to use when looking up entities that - /// are needed for parsing (locations of variables, etc.) - /// - /// @param[in] options - /// Expression evaluation options. - /// - /// @param[in] shared_ptr_to_me - /// This is a shared pointer to this ClangUserExpression. This is - /// needed because Execute can push a thread plan that will hold onto - /// the ClangUserExpression for an unbounded period of time. So you - /// need to give the thread plan a reference to this object that can - /// keep it alive. - /// - /// @param[in] result - /// A pointer to direct at the persistent variable in which the - /// expression's result is stored. - /// - /// @return - /// A Process::Execution results value. - //------------------------------------------------------------------ - lldb::ExpressionResults - Execute (Stream &error_stream, - ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - lldb::ClangUserExpressionSP &shared_ptr_to_me, - lldb::ClangExpressionVariableSP &result); - - //------------------------------------------------------------------ - /// Apply the side effects of the function to program state. - /// - /// @param[in] error_stream - /// A stream to print errors to. - /// - /// @param[in] exe_ctx - /// The execution context to use when looking up entities that - /// are needed for parsing (locations of variables, etc.) - /// - /// @param[in] result - /// A pointer to direct at the persistent variable in which the - /// expression's result is stored. - /// - /// @param[in] function_stack_pointer - /// A pointer to the base of the function's stack frame. This - /// is used to determine whether the expression result resides in - /// memory that will still be valid, or whether it needs to be - /// treated as homeless for the purpose of future expressions. - /// - /// @return - /// A Process::Execution results value. - //------------------------------------------------------------------ - bool - FinalizeJITExecution (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP &result, - lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, - lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS); - - //------------------------------------------------------------------ - /// Return the string that the parser should parse. Must be a full - /// translation unit. - //------------------------------------------------------------------ - const char * - Text () - { - return m_transformed_text.c_str(); - } - - //------------------------------------------------------------------ - /// Return the string that the user typed. - //------------------------------------------------------------------ - const char * - GetUserText () - { - return m_expr_text.c_str(); - } - - //------------------------------------------------------------------ - /// Return the function name that should be used for executing the - /// expression. Text() should contain the definition of this - /// function. - //------------------------------------------------------------------ - const char * - FunctionName () - { - return "$__lldb_expr"; - } - - //------------------------------------------------------------------ - /// Return the language that should be used when parsing. To use - /// the default, return eLanguageTypeUnknown. - //------------------------------------------------------------------ - virtual lldb::LanguageType - Language () - { - return m_language; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap () - { - return m_expr_decl_map.get(); - } - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer (clang::ASTConsumer *passthrough); - - //------------------------------------------------------------------ - /// Return the desired result type of the function, or - /// eResultTypeAny if indifferent. - //------------------------------------------------------------------ - virtual ResultType - DesiredResultType () - { - return m_desired_type; - } - - //------------------------------------------------------------------ - /// Return true if validation code should be inserted into the - /// expression. - //------------------------------------------------------------------ - bool - NeedsValidation () - { - return true; - } - - //------------------------------------------------------------------ - /// Return true if external variables in the expression should be - /// resolved. - //------------------------------------------------------------------ - bool - NeedsVariableResolution () - { - return true; - } - - //------------------------------------------------------------------ - /// Evaluate one expression and return its result. - /// - /// @param[in] exe_ctx - /// The execution context to use when evaluating the expression. - /// - /// @param[in] options - /// Expression evaluation options. - /// - /// @param[in] expr_cstr - /// A C string containing the expression to be evaluated. - /// - /// @param[in] expr_prefix - /// If non-NULL, a C string containing translation-unit level - /// definitions to be included when the expression is parsed. - /// - /// @param[in/out] result_valobj_sp - /// If execution is successful, the result valobj is placed here. - /// - /// @param[out] - /// Filled in with an error in case the expression evaluation - /// fails to parse, run, or evaluated. - /// - /// @result - /// A Process::ExpressionResults value. eExpressionCompleted for success. - //------------------------------------------------------------------ - static lldb::ExpressionResults - Evaluate (ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error); - - static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. -private: - //------------------------------------------------------------------ - /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. - //------------------------------------------------------------------ - - void - ScanContext (ExecutionContext &exe_ctx, - lldb_private::Error &err); - - bool - PrepareToExecuteJITExpression (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::addr_t &struct_address, - lldb::addr_t &object_ptr, - lldb::addr_t &cmd_ptr); - - void - InstallContext (ExecutionContext &exe_ctx); - - bool - LockAndCheckContext (ExecutionContext &exe_ctx, - lldb::TargetSP &target_sp, - lldb::ProcessSP &process_sp, - lldb::StackFrameSP &frame_sp); - - lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression. - Address m_address; ///< The address the process is stopped in. - lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame. - lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame. - - std::string m_expr_text; ///< The text of the expression, as typed by the user - std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user - lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults) - bool m_allow_cxx; ///< True if the language allows C++. - bool m_allow_objc; ///< True if the language allows Objective-C. - std::string m_transformed_text; ///< The text of the expression, as send to the parser - ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression. - - std::unique_ptr m_expr_decl_map; ///< The map to use when parsing the expression. - std::shared_ptr m_execution_unit_sp; ///< The execution unit the expression is stored in. - std::unique_ptr m_materializer_ap; ///< The materializer to use when running the expression. - std::unique_ptr m_result_synthesizer; ///< The result synthesizer, if one is needed. - lldb::ModuleWP m_jit_module_wp; - bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method. - bool m_in_cplusplus_method; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). - bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method). - bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method). - bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL. - bool m_const_object; ///< True if "this" is const. - Target *m_target; ///< The target for storing persistent data like types and variables. - - bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise. - lldb::addr_t m_materialized_address; ///< The address at which the arguments to the expression have been materialized. - Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer. -}; - -} // namespace lldb_private - -#endif // liblldb_ClangUserExpression_h_ diff --git a/include/lldb/Expression/ClangUtilityFunction.h b/include/lldb/Expression/ClangUtilityFunction.h deleted file mode 100644 index bb5601fa2914..000000000000 --- a/include/lldb/Expression/ClangUtilityFunction.h +++ /dev/null @@ -1,179 +0,0 @@ -//===-- ClangUtilityFunction.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_ClangUtilityFunction_h_ -#define liblldb_ClangUtilityFunction_h_ - -// C Includes -// C++ Includes -#include -#include -#include - -// Other libraries and framework includes -// Project includes - -#include "lldb/lldb-forward.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" -#include "lldb/Expression/ClangExpression.h" - -namespace lldb_private -{ - -//---------------------------------------------------------------------- -/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" -/// @brief Encapsulates a single expression for use with Clang -/// -/// LLDB uses expressions for various purposes, notably to call functions -/// and as a backend for the expr command. ClangUtilityFunction encapsulates -/// a self-contained function meant to be used from other code. Utility -/// functions can perform error-checking for ClangUserExpressions, -//---------------------------------------------------------------------- -class ClangUtilityFunction : public ClangExpression -{ -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] text - /// The text of the function. Must be a full translation unit. - /// - /// @param[in] name - /// The name of the function, as used in the text. - //------------------------------------------------------------------ - ClangUtilityFunction (const char *text, - const char *name); - - virtual - ~ClangUtilityFunction (); - - //------------------------------------------------------------------ - /// Install the utility function into a process - /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. - /// - /// @param[in] exe_ctx - /// The execution context to install the utility function to. - /// - /// @return - /// True on success (no errors); false otherwise. - //------------------------------------------------------------------ - bool - Install (Stream &error_stream, ExecutionContext &exe_ctx); - - //------------------------------------------------------------------ - /// Check whether the given PC is inside the function - /// - /// Especially useful if the function dereferences NULL to indicate a failed - /// assert. - /// - /// @param[in] pc - /// The program counter to check. - /// - /// @return - /// True if the program counter falls within the function's bounds; - /// false if not (or the function is not JIT compiled) - //------------------------------------------------------------------ - bool - ContainsAddress (lldb::addr_t address) - { - // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, - // so this always returns false if the function is not JIT compiled yet - return (address >= m_jit_start_addr && address < m_jit_end_addr); - } - - - //------------------------------------------------------------------ - /// Return the string that the parser should parse. Must be a full - /// translation unit. - //------------------------------------------------------------------ - const char * - Text () - { - return m_function_text.c_str(); - } - - //------------------------------------------------------------------ - /// Return the function name that should be used for executing the - /// expression. Text() should contain the definition of this - /// function. - //------------------------------------------------------------------ - const char * - FunctionName () - { - return m_function_name.c_str(); - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when resolving external - /// values. May be NULL if everything should be self-contained. - //------------------------------------------------------------------ - ClangExpressionDeclMap * - DeclMap () - { - return m_expr_decl_map.get(); - } - - //------------------------------------------------------------------ - /// Return the object that the parser should use when registering - /// local variables. May be NULL if the Expression doesn't care. - //------------------------------------------------------------------ - ClangExpressionVariableList * - LocalVariables () - { - return NULL; - } - - //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. - /// - /// @param[in] passthrough - /// The ASTConsumer that the returned transformer should send - /// the ASTs to after transformation. - //------------------------------------------------------------------ - clang::ASTConsumer * - ASTTransformer (clang::ASTConsumer *passthrough) - { - return NULL; - } - - //------------------------------------------------------------------ - /// Return true if validation code should be inserted into the - /// expression. - //------------------------------------------------------------------ - bool - NeedsValidation () - { - return false; - } - - //------------------------------------------------------------------ - /// Return true if external variables in the expression should be - /// resolved. - //------------------------------------------------------------------ - bool - NeedsVariableResolution () - { - return false; - } - -private: - std::unique_ptr m_expr_decl_map; ///< The map to use when parsing and materializing the expression. - std::shared_ptr m_execution_unit_sp; - lldb::ModuleWP m_jit_module_wp; - std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit. - std::string m_function_name; ///< The name of the function. -}; - -} // namespace lldb_private - -#endif // liblldb_ClangUtilityFunction_h_ diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h index 9ddecc053e00..3527c3b4b153 100644 --- a/include/lldb/Expression/DWARFExpression.h +++ b/include/lldb/Expression/DWARFExpression.h @@ -11,18 +11,19 @@ #define liblldb_DWARFExpression_h_ #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Scalar.h" +class DWARFCompileUnit; + namespace lldb_private { +class ClangExpressionDeclMap; class ClangExpressionVariable; class ClangExpressionVariableList; -class ClangExpressionDeclMap; //---------------------------------------------------------------------- /// @class DWARFExpression DWARFExpression.h "lldb/Expression/DWARFExpression.h" @@ -40,10 +41,17 @@ class ClangExpressionDeclMap; class DWARFExpression { 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 + }; + //------------------------------------------------------------------ /// Constructor //------------------------------------------------------------------ - DWARFExpression(); + explicit DWARFExpression(DWARFCompileUnit* dwarf_cu); //------------------------------------------------------------------ /// Constructor @@ -60,6 +68,7 @@ public: //------------------------------------------------------------------ DWARFExpression(lldb::ModuleSP module, const DataExtractor& data, + DWARFCompileUnit* dwarf_cu, lldb::offset_t data_offset, lldb::offset_t data_length); @@ -356,6 +365,7 @@ public: RegisterContext *reg_ctx, lldb::ModuleSP opcode_ctx, const DataExtractor& opcodes, + DWARFCompileUnit* dwarf_cu, const lldb::offset_t offset, const lldb::offset_t length, const lldb::RegisterKind reg_set, @@ -397,6 +407,24 @@ public: lldb::addr_t address, ABI *abi); + static size_t + LocationListSize(const DWARFCompileUnit* dwarf_cu, + const DataExtractor& debug_loc_data, + lldb::offset_t offset); + + static bool + PrintDWARFExpression(Stream &s, + const DataExtractor& data, + int address_size, + int dwarf_ref_size, + bool location_expression); + + static void + PrintDWARFLocationList(Stream &s, + const DWARFCompileUnit* cu, + const DataExtractor& debug_loc_data, + lldb::offset_t offset); + protected: //------------------------------------------------------------------ /// Pretty-prints the location expression to a stream @@ -430,17 +458,26 @@ protected: lldb::offset_t &offset, lldb::offset_t &len); + static bool + AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu, + const DataExtractor& debug_loc_data, + lldb::offset_t* offset_ptr, + lldb::addr_t& low_pc, + lldb::addr_t& high_pc); + //------------------------------------------------------------------ /// Classes that inherit from DWARFExpression can see and modify these //------------------------------------------------------------------ lldb::ModuleWP m_module_wp; ///< Module which defined this expression. DataExtractor m_data; ///< A data extractor capable of reading opcode bytes + DWARFCompileUnit* m_dwarf_cu; ///< The DWARF compile unit this expression belongs to. It is used + ///< to evaluate values indexing into the .debug_addr section (e.g. + ///< DW_OP_GNU_addr_index, DW_OP_GNU_const_index) lldb::RegisterKind m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_ lldb::addr_t m_loclist_slide; ///< A value used to slide the location list offsets so that ///< they are relative to the object that owns the location list ///< (the function for frame base and variable location lists) - }; } // namespace lldb_private diff --git a/include/lldb/Expression/Expression.h b/include/lldb/Expression/Expression.h new file mode 100644 index 000000000000..b5c2d575ae04 --- /dev/null +++ b/include/lldb/Expression/Expression.h @@ -0,0 +1,141 @@ +//===-- Expression.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_Expression_h_ +#define liblldb_Expression_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Expression/ExpressionTypeSystemHelper.h" + +namespace lldb_private { + +class RecordingMemoryManager; + +//---------------------------------------------------------------------- +/// @class Expression Expression.h "lldb/Expression/Expression.h" +/// @brief Encapsulates a single expression for use in lldb +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. Expression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the expression parser appropriate to the language of the expression +/// to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class Expression +{ +public: + enum ResultType { + eResultTypeAny, + eResultTypeId + }; + + Expression (Target &target); + + Expression (ExecutionContextScope &exe_scope); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~Expression () + { + } + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + virtual const char * + Text () = 0; + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + virtual const char * + FunctionName () = 0; + + //------------------------------------------------------------------ + /// Return the language that should be used when parsing. To use + /// the default, return eLanguageTypeUnknown. + //------------------------------------------------------------------ + virtual lldb::LanguageType + Language () + { + return lldb::eLanguageTypeUnknown; + } + + //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + virtual ResultType + DesiredResultType () + { + return eResultTypeAny; + } + + //------------------------------------------------------------------ + /// Flags + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + virtual bool + NeedsValidation () = 0; + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + virtual bool + NeedsVariableResolution () = 0; + + virtual EvaluateExpressionOptions *GetOptions() { return nullptr; }; + + //------------------------------------------------------------------ + /// Return the address of the function's JIT-compiled code, or + /// LLDB_INVALID_ADDRESS if the function is not JIT compiled + //------------------------------------------------------------------ + lldb::addr_t + StartAddress () + { + return m_jit_start_addr; + } + + virtual ExpressionTypeSystemHelper * + GetTypeSystemHelper () + { + return nullptr; + } + +protected: + + lldb::TargetWP m_target_wp; /// Expression's always have to have a target... + lldb::ProcessWP m_jit_process_wp; /// An expression might have a process, but it doesn't need to (e.g. calculator mode.) + lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. + lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. + +}; + +} // namespace lldb_private + +#endif // liblldb_Expression_h_ diff --git a/include/lldb/Expression/ExpressionParser.h b/include/lldb/Expression/ExpressionParser.h new file mode 100644 index 000000000000..49333e79bf5e --- /dev/null +++ b/include/lldb/Expression/ExpressionParser.h @@ -0,0 +1,123 @@ +//===-- ExpressionParser.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_ExpressionParser_h_ +#define liblldb_ExpressionParser_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/Error.h" + +namespace lldb_private +{ + +class IRExecutionUnit; + +//---------------------------------------------------------------------- +/// @class ExpressionParser ExpressionParser.h "lldb/Expression/ExpressionParser.h" +/// @brief Encapsulates an instance of a compiler that can parse expressions. +/// +/// ExpressionParser is the base class for llvm based Expression parsers. +//---------------------------------------------------------------------- +class ExpressionParser +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] exe_scope, + /// If non-NULL, an execution context scope that can help to + /// correctly create an expression with a valid process for + /// optional tuning Objective-C runtime support. Can be NULL. + /// + /// @param[in] expr + /// The expression to be parsed. + //------------------------------------------------------------------ + ExpressionParser (ExecutionContextScope *exe_scope, + Expression &expr, + bool generate_debug_info) : + m_expr(expr), + m_generate_debug_info(generate_debug_info) + { + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~ExpressionParser () {}; + + //------------------------------------------------------------------ + /// Parse a single expression and convert it to IR using Clang. Don't + /// wrap the expression in anything at all. + /// + /// @param[in] stream + /// The stream to print errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + virtual unsigned + Parse (Stream &stream) = 0; + + //------------------------------------------------------------------ + /// Ready an already-parsed expression for execution, possibly + /// evaluating it statically. + /// + /// @param[out] func_addr + /// The address to which the function has been written. + /// + /// @param[out] func_end + /// The end of the function's allocated memory region. (func_addr + /// and func_end do not delimit an allocated region; the allocated + /// region may begin before func_addr.) + /// + /// @param[in] execution_unit_sp + /// After parsing, ownership of the execution unit for + /// for the expression is handed to this shared pointer. + /// + /// @param[in] exe_ctx + /// The execution context to write the function into. + /// + /// @param[out] can_interpret + /// Set to true if the expression could be interpreted statically; + /// untouched otherwise. + /// + /// @param[in] execution_policy + /// Determines whether the expression must be JIT-compiled, must be + /// evaluated statically, or whether this decision may be made + /// opportunistically. + /// + /// @return + /// An error code indicating the success or failure of the operation. + /// Test with Success(). + //------------------------------------------------------------------ + virtual Error + PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + std::shared_ptr &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) = 0; + + bool + GetGenerateDebugInfo () const + { + return m_generate_debug_info; + } + +protected: + Expression & m_expr; ///< The expression to be parsed + bool m_generate_debug_info; +}; + +} + +#endif // liblldb_ExpressionParser_h_ diff --git a/include/lldb/Expression/ExpressionTypeSystemHelper.h b/include/lldb/Expression/ExpressionTypeSystemHelper.h new file mode 100644 index 000000000000..cb560c9b5a42 --- /dev/null +++ b/include/lldb/Expression/ExpressionTypeSystemHelper.h @@ -0,0 +1,54 @@ +//===-- ExpressionTypeSystemHelper.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ExpressionTypeSystemHelper_h +#define ExpressionTypeSystemHelper_h + +#include "llvm/Support/Casting.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h "lldb/Expression/ExpressionTypeSystemHelper.h" +/// @brief A helper object that the Expression can pass to its ExpressionParser to provide generic information that +/// any type of expression will need to supply. It's only job is to support dyn_cast so that the expression parser +/// can cast it back to the requisite specific type. +/// +//---------------------------------------------------------------------- + +class ExpressionTypeSystemHelper +{ +public: + enum LLVMCastKind { + eKindClangHelper, + eKindSwiftHelper, + eKindGoHelper, + kNumKinds + }; + + LLVMCastKind getKind() const { return m_kind; } + + ExpressionTypeSystemHelper (LLVMCastKind kind) : + m_kind(kind) + { + } + + ~ExpressionTypeSystemHelper () {} + +protected: + LLVMCastKind m_kind; +}; + + + + +} // namespace lldb_private + +#endif /* ExpressionTypeSystemHelper_h */ diff --git a/include/lldb/Expression/ExpressionVariable.h b/include/lldb/Expression/ExpressionVariable.h new file mode 100644 index 000000000000..d8030ba1c257 --- /dev/null +++ b/include/lldb/Expression/ExpressionVariable.h @@ -0,0 +1,320 @@ +//===-- ExpressionVariable.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_ExpressionVariable_h_ +#define liblldb_ExpressionVariable_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ValueObject.h" + +namespace lldb_private +{ + +class ClangExpressionVariable; + +class ExpressionVariable : + public std::enable_shared_from_this +{ +public: + //---------------------------------------------------------------------- + // See TypeSystem.h for how to add subclasses to this. + //---------------------------------------------------------------------- + enum LLVMCastKind { + eKindClang, + eKindSwift, + eKindGo, + kNumKinds + }; + + LLVMCastKind getKind() const { return m_kind; } + + ExpressionVariable(LLVMCastKind kind) : + m_flags(0), + m_kind(kind) + { + } + + virtual ~ExpressionVariable(); + + size_t + GetByteSize () + { + return m_frozen_sp->GetByteSize(); + } + + const ConstString & + GetName () + { + return m_frozen_sp->GetName(); + } + + lldb::ValueObjectSP + GetValueObject() + { + return m_frozen_sp; + } + + uint8_t *GetValueBytes(); + + void + ValueUpdated () + { + m_frozen_sp->ValueUpdated (); + } + + RegisterInfo * + GetRegisterInfo() + { + return m_frozen_sp->GetValue().GetRegisterInfo(); + } + + void + SetRegisterInfo (const RegisterInfo *reg_info) + { + return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast(reg_info)); + } + + CompilerType + GetCompilerType() + { + return m_frozen_sp->GetCompilerType(); + } + + void + SetCompilerType(const CompilerType &compiler_type) + { + m_frozen_sp->GetValue().SetCompilerType(compiler_type); + } + + void + SetName (const ConstString &name) + { + m_frozen_sp->SetName (name); + } + + // this function is used to copy the address-of m_live_sp into m_frozen_sp + // this is necessary because the results of certain cast and pointer-arithmetic + // operations (such as those described in bugzilla issues 11588 and 11618) generate + // frozen objects that do not have a valid address-of, which can be troublesome when + // using synthetic children providers. Transferring the address-of the live object + // solves these issues and provides the expected user-level behavior + void + TransferAddress (bool force = false) + { + if (m_live_sp.get() == nullptr) + return; + + if (m_frozen_sp.get() == nullptr) + return; + + if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS)) + m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress()); + } + + enum Flags + { + EVNone = 0, + EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process + EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program + EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process + EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results) + EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization + EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it + EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location + EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete + EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or some other entity. + }; + + typedef uint16_t FlagType; + + FlagType m_flags; // takes elements of Flags + + // these should be private + lldb::ValueObjectSP m_frozen_sp; + lldb::ValueObjectSP m_live_sp; + LLVMCastKind m_kind; +}; + +//---------------------------------------------------------------------- +/// @class ExpressionVariableList ExpressionVariable.h "lldb/Expression/ExpressionVariable.h" +/// @brief A list of variable references. +/// +/// This class stores variables internally, acting as the permanent store. +//---------------------------------------------------------------------- +class ExpressionVariableList +{ +public: + //---------------------------------------------------------------------- + /// Implementation of methods in ExpressionVariableListBase + //---------------------------------------------------------------------- + size_t + GetSize() + { + return m_variables.size(); + } + + lldb::ExpressionVariableSP + GetVariableAtIndex(size_t index) + { + lldb::ExpressionVariableSP var_sp; + if (index < m_variables.size()) + var_sp = m_variables[index]; + return var_sp; + } + + size_t + AddVariable (const lldb::ExpressionVariableSP &var_sp) + { + m_variables.push_back(var_sp); + return m_variables.size() - 1; + } + + lldb::ExpressionVariableSP + AddNewlyConstructedVariable (ExpressionVariable *var) + { + lldb::ExpressionVariableSP var_sp(var); + m_variables.push_back(var_sp); + return m_variables.back(); + } + + bool + ContainsVariable (const lldb::ExpressionVariableSP &var_sp) + { + const size_t size = m_variables.size(); + for (size_t index = 0; index < size; ++index) + { + if (m_variables[index].get() == var_sp.get()) + return true; + } + return false; + } + + //---------------------------------------------------------------------- + /// Finds a variable by name in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or nullptr if that variable is not in the list. + //---------------------------------------------------------------------- + lldb::ExpressionVariableSP + GetVariable (const ConstString &name) + { + lldb::ExpressionVariableSP var_sp; + for (size_t index = 0, size = GetSize(); index < size; ++index) + { + var_sp = GetVariableAtIndex(index); + if (var_sp->GetName() == name) + return var_sp; + } + var_sp.reset(); + return var_sp; + } + + lldb::ExpressionVariableSP + GetVariable (const char *name) + { + lldb::ExpressionVariableSP var_sp; + if (name && name[0]) + { + for (size_t index = 0, size = GetSize(); index < size; ++index) + { + var_sp = GetVariableAtIndex(index); + const char *var_name_cstr = var_sp->GetName().GetCString(); + if (!var_name_cstr || !name) + continue; + if (::strcmp (var_name_cstr, name) == 0) + return var_sp; + } + var_sp.reset(); + } + return var_sp; + } + + void + RemoveVariable (lldb::ExpressionVariableSP var_sp) + { + for (std::vector::iterator vi = m_variables.begin(), ve = m_variables.end(); + vi != ve; + ++vi) + { + if (vi->get() == var_sp.get()) + { + m_variables.erase(vi); + return; + } + } + } + + void + Clear() + { + m_variables.clear(); + } + +private: + std::vector m_variables; +}; + +class PersistentExpressionState : public ExpressionVariableList { +public: + //---------------------------------------------------------------------- + // See TypeSystem.h for how to add subclasses to this. + //---------------------------------------------------------------------- + enum LLVMCastKind { + eKindClang, + eKindSwift, + eKindGo, + kNumKinds + }; + + LLVMCastKind getKind() const { return m_kind; } + + PersistentExpressionState(LLVMCastKind kind) : + m_kind(kind) + { + } + + virtual ~PersistentExpressionState(); + + virtual lldb::ExpressionVariableSP + CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) = 0; + + virtual lldb::ExpressionVariableSP + CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const CompilerType &type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) = 0; + + virtual ConstString + GetNextPersistentVariableName () = 0; + + virtual void + RemovePersistentVariable (lldb::ExpressionVariableSP variable) = 0; + + virtual lldb::addr_t + LookupSymbol (const ConstString &name) = 0; + +private: + LLVMCastKind m_kind; +}; + +} // namespace lldb_private + +#endif // liblldb_ExpressionVariable_h_ diff --git a/include/lldb/Expression/FunctionCaller.h b/include/lldb/Expression/FunctionCaller.h new file mode 100644 index 000000000000..c9a45811670f --- /dev/null +++ b/include/lldb/Expression/FunctionCaller.h @@ -0,0 +1,395 @@ +//===-- FunctionCaller.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_FunctionCaller_h_ +#define liblldb_FunctionCaller_h_ + +// C Includes +// C++ Includes +#include +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Address.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/Expression.h" +#include "lldb/Expression/ExpressionParser.h" +#include "lldb/Symbol/CompilerType.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h" +/// @brief Encapsulates a function that can be called. +/// +/// A given FunctionCaller object can handle a single function signature. +/// Once constructed, it can set up any number of concurrent calls to +/// functions with that signature. +/// +/// It performs the call by synthesizing a structure that contains the pointer +/// to the function and the arguments that should be passed to that function, +/// and producing a special-purpose JIT-compiled function that accepts a void* +/// pointing to this struct as its only argument and calls the function in the +/// struct with the written arguments. This method lets Clang handle the +/// vagaries of function calling conventions. +/// +/// The simplest use of the FunctionCaller is to construct it with a +/// function representative of the signature you want to use, then call +/// ExecuteFunction(ExecutionContext &, Stream &, Value &). +/// +/// If you need to reuse the arguments for several calls, you can call +/// InsertFunction() followed by WriteFunctionArguments(), which will return +/// the location of the args struct for the wrapper function in args_addr_ref. +/// +/// If you need to call the function on the thread plan stack, you can also +/// call InsertFunction() followed by GetThreadPlanToCallFunction(). +/// +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed +/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// and its address returned in that variable. +/// +/// Any of the methods that take arg_addr_ptr can be passed nullptr, and the +/// argument space will be managed for you. +//---------------------------------------------------------------------- +class FunctionCaller : public Expression +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + FunctionCaller (ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~FunctionCaller() override; + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] errors + /// The stream to print parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + virtual unsigned + CompileFunction (Stream &errors) = 0; + + //------------------------------------------------------------------ + /// Insert the default function wrapper and its default argument struct + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed to it. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + InsertFunction (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert the default function wrapper (using the JIT) + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionWrapper (ExecutionContext &exe_ctx, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert the default function argument struct + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed to it. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionArguments (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert an argument struct with a non-default function address and + /// non-default argument values + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed at it. + /// + /// @param[in] arg_values + /// The values of the function's arguments. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionArguments (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + ValueList &arg_values, + Stream &errors); + + //------------------------------------------------------------------ + /// Run the function this FunctionCaller was created with. + /// + /// This is the full version. + /// + /// @param[in] exe_ctx + /// The thread & process in which this function will run. + /// + /// @param[in] args_addr_ptr + /// If nullptr, the function will take care of allocating & deallocating the wrapper + /// args structure. Otherwise, if set to LLDB_INVALID_ADDRESS, a new structure + /// will be allocated, filled and the address returned to you. You are responsible + /// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS, + /// this should point to an already allocated structure with the values already written. + /// + /// @param[in] errors + /// Errors will be written here if there are any. + /// + /// @param[in] options + /// The options for this expression execution. + /// + /// @param[out] results + /// The result value will be put here after running the function. + /// + /// @return + /// Returns one of the ExpressionResults enum indicating function call status. + //------------------------------------------------------------------ + lldb::ExpressionResults + ExecuteFunction(ExecutionContext &exe_ctx, + lldb::addr_t *args_addr_ptr, + const EvaluateExpressionOptions &options, + Stream &errors, + Value &results); + + //------------------------------------------------------------------ + /// Get a thread plan to run the function this FunctionCaller was created with. + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] func_addr + /// The address of the function in the target process. + /// + /// @param[in] args_addr + /// The address of the argument struct. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @param[in] stop_others + /// True if other threads should pause during execution. + /// + /// @param[in] unwind_on_error + /// True if the thread plan may simply be discarded if an error occurs. + /// + /// @return + /// A ThreadPlan shared pointer for executing the function. + //------------------------------------------------------------------ + lldb::ThreadPlanSP + GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, + lldb::addr_t args_addr, + const EvaluateExpressionOptions &options, + Stream &errors); + + //------------------------------------------------------------------ + /// Get the result of the function from its struct + /// + /// @param[in] exe_ctx + /// The execution context to retrieve the result from. + /// + /// @param[in] args_addr + /// The address of the argument struct. + /// + /// @param[out] ret_value + /// The value returned by the function. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool FetchFunctionResults (ExecutionContext &exe_ctx, + lldb::addr_t args_addr, + Value &ret_value); + + //------------------------------------------------------------------ + /// Deallocate the arguments structure + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] args_addr + /// The address of the argument struct. + //------------------------------------------------------------------ + void DeallocateFunctionResults (ExecutionContext &exe_ctx, + lldb::addr_t args_addr); + + //------------------------------------------------------------------ + /// Interface for ClangExpression + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text() override + { + return m_wrapper_function_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName() override + { + return m_wrapper_function_name.c_str(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when registering + /// local variables. May be nullptr if the Expression doesn't care. + //------------------------------------------------------------------ + ExpressionVariableList * + LocalVariables () + { + return nullptr; + } + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation() override + { + return false; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution() override + { + return false; + } + + ValueList + GetArgumentValues () const + { + return m_arg_values; + } + +protected: + // Note: the parser needs to be destructed before the execution unit, so + // declare the execution unit first. + std::shared_ptr m_execution_unit_sp; + std::unique_ptr m_parser; ///< The parser responsible for compiling the function. + ///< This will get made in CompileFunction, so it is + ///< safe to access it after that. + + lldb::ModuleWP m_jit_module_wp; + std::string m_name; ///< The name of this clang function - for debugging purposes. + + Function *m_function_ptr; ///< The function we're going to call. May be nullptr if we don't have debug info for the function. + Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type. + CompilerType m_function_return_type; ///< The opaque clang qual type for the function return type. + + std::string m_wrapper_function_name; ///< The name of the wrapper function. + std::string m_wrapper_function_text; ///< The contents of the wrapper function. + std::string m_wrapper_struct_name; ///< The name of the struct that contains the target function address, arguments, and result. + std::list m_wrapper_args_addrs; ///< The addresses of the arguments to the wrapper function. + + bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below. + + //------------------------------------------------------------------ + /// These values are populated by the ASTStructExtractor + size_t m_struct_size; ///< The size of the argument struct, in bytes. + std::vector m_member_offsets; ///< The offset of each member in the struct, in bytes. + uint64_t m_return_size; ///< The size of the result variable, in bytes. + uint64_t m_return_offset; ///< The offset of the result variable in the struct, in bytes. + //------------------------------------------------------------------ + + ValueList m_arg_values; ///< The default values of the arguments. + + bool m_compiled; ///< True if the wrapper function has already been parsed. + bool m_JITted; ///< True if the wrapper function has already been JIT-compiled. +}; + +} // namespace lldb_private + +#endif // liblldb_FunctionCaller_h_ diff --git a/include/lldb/Expression/IRDynamicChecks.h b/include/lldb/Expression/IRDynamicChecks.h index 226f5c94e98c..ef77d55f4b34 100644 --- a/include/lldb/Expression/IRDynamicChecks.h +++ b/include/lldb/Expression/IRDynamicChecks.h @@ -24,11 +24,10 @@ namespace llvm { class Value; } -namespace lldb_private +namespace lldb_private { class ClangExpressionDeclMap; -class ClangUtilityFunction; class ExecutionContext; class Stream; @@ -77,8 +76,8 @@ public: bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message); - std::unique_ptr m_valid_pointer_check; - std::unique_ptr m_objc_object_check; + std::unique_ptr m_valid_pointer_check; + std::unique_ptr m_objc_object_check; }; //---------------------------------------------------------------------- @@ -114,7 +113,7 @@ public: //------------------------------------------------------------------ /// Destructor //------------------------------------------------------------------ - virtual ~IRDynamicChecks(); + ~IRDynamicChecks() override; //------------------------------------------------------------------ /// Run this IR transformer on a single module @@ -127,18 +126,19 @@ public: /// @return /// True on success; false otherwise //------------------------------------------------------------------ - bool runOnModule(llvm::Module &M); + bool runOnModule(llvm::Module &M) override; //------------------------------------------------------------------ /// Interface stub //------------------------------------------------------------------ void assignPassManager(llvm::PMStack &PMS, - llvm::PassManagerType T = llvm::PMT_ModulePassManager); + llvm::PassManagerType T = llvm::PMT_ModulePassManager) override; //------------------------------------------------------------------ /// Returns PMT_ModulePassManager //------------------------------------------------------------------ - llvm::PassManagerType getPotentialPassManagerType() const; + llvm::PassManagerType getPotentialPassManagerType() const override; + private: //------------------------------------------------------------------ /// A basic block-level pass to find all pointer dereferences and @@ -164,6 +164,6 @@ private: DynamicCheckerFunctions &m_checker_functions; ///< The checker functions for the process }; -} +} // namespace lldb_private -#endif +#endif // liblldb_IRDynamicChecks_h_ diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index bd1a795a158e..86744b7b9726 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -7,27 +7,24 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_IRExecutionUnit_h_ -#define lldb_IRExecutionUnit_h_ +#ifndef liblldb_IRExecutionUnit_h_ +#define liblldb_IRExecutionUnit_h_ // C Includes // C++ Includes #include +#include #include #include -#include // Other libraries and framework includes #include "llvm/IR/Module.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" // Project includes #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" #include "lldb/Core/DataBufferHeap.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangExpressionParser.h" #include "lldb/Expression/IRMemoryMap.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/ObjectFile.h" @@ -37,7 +34,7 @@ namespace llvm { class Module; class ExecutionEngine; -} +} // namespace llvm namespace lldb_private { @@ -79,7 +76,7 @@ public: //------------------------------------------------------------------ /// Destructor //------------------------------------------------------------------ - ~IRExecutionUnit(); + ~IRExecutionUnit() override; llvm::Module * GetModule() @@ -90,10 +87,7 @@ public: llvm::Function * GetFunction() { - if (m_module) - return m_module->getFunction (m_name.AsCString()); - else - return NULL; + return ((m_module != nullptr) ? m_module->getFunction(m_name.AsCString()) : nullptr); } void @@ -118,22 +112,22 @@ public: //------------------------------------------------------------------ /// ObjectFileJITDelegate overrides //------------------------------------------------------------------ - virtual lldb::ByteOrder - GetByteOrder () const; + lldb::ByteOrder + GetByteOrder() const override; - virtual uint32_t - GetAddressByteSize () const; + uint32_t + GetAddressByteSize() const override; - virtual void - PopulateSymtab (lldb_private::ObjectFile *obj_file, - lldb_private::Symtab &symtab); + void + PopulateSymtab(lldb_private::ObjectFile *obj_file, + lldb_private::Symtab &symtab) override; - virtual void - PopulateSectionList (lldb_private::ObjectFile *obj_file, - lldb_private::SectionList §ion_list); + void + PopulateSectionList(lldb_private::ObjectFile *obj_file, + lldb_private::SectionList §ion_list) override; - virtual bool - GetArchitecture (lldb_private::ArchSpec &arch); + bool + GetArchitecture(lldb_private::ArchSpec &arch) override; lldb::ModuleSP GetJITModule (); @@ -215,7 +209,7 @@ private: public: MemoryManager (IRExecutionUnit &parent); - virtual ~MemoryManager(); + ~MemoryManager() override; //------------------------------------------------------------------ /// Allocate space for executable code, and add it to the @@ -233,9 +227,9 @@ private: /// @return /// Allocated space. //------------------------------------------------------------------ - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - llvm::StringRef SectionName); + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + llvm::StringRef SectionName) override; //------------------------------------------------------------------ /// Allocate space for data, and add it to the m_spaceBlocks map @@ -255,10 +249,10 @@ private: /// @return /// Allocated space. //------------------------------------------------------------------ - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - llvm::StringRef SectionName, - bool IsReadOnly); + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + llvm::StringRef SectionName, + bool IsReadOnly) override; //------------------------------------------------------------------ /// Called when object loading is complete and section page @@ -270,7 +264,7 @@ private: /// @return /// True in case of failure, false in case of success. //------------------------------------------------------------------ - virtual bool finalizeMemory(std::string *ErrMsg) { + bool finalizeMemory(std::string *ErrMsg) override { // TODO: Ensure that the instruction cache is flushed because // relocations are updated by dy-load. See: // sys::Memory::InvalidateInstructionCache @@ -278,17 +272,17 @@ private: return false; } - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { - return; + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override { } //------------------------------------------------------------------ /// Passthrough interface stub //------------------------------------------------------------------ - virtual uint64_t getSymbolAddress(const std::string &Name); + uint64_t getSymbolAddress(const std::string &Name) override; + + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override; - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true); private: std::unique_ptr m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. @@ -403,4 +397,4 @@ private: } // namespace lldb_private -#endif // lldb_IRExecutionUnit_h_ +#endif // liblldb_IRExecutionUnit_h_ diff --git a/include/lldb/Expression/IRForTarget.h b/include/lldb/Expression/IRForTarget.h deleted file mode 100644 index b81fab7a8a83..000000000000 --- a/include/lldb/Expression/IRForTarget.h +++ /dev/null @@ -1,745 +0,0 @@ -//===-- IRForTarget.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_IRForTarget_h_ -#define liblldb_IRForTarget_h_ - -#include "lldb/lldb-public.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Symbol/TaggedASTType.h" -#include "llvm/Pass.h" - -#include -#include - -namespace llvm { - class BasicBlock; - class CallInst; - class Constant; - class ConstantInt; - class Function; - class GlobalValue; - class GlobalVariable; - class Instruction; - class IntegerType; - class Module; - class StoreInst; - class DataLayout; - class Type; - class Value; -} - -namespace lldb_private { - class ClangExpressionDeclMap; - class IRExecutionUnit; - class IRMemoryMap; -} - -//---------------------------------------------------------------------- -/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" -/// @brief Transforms the IR for a function to run in the target -/// -/// Once an expression has been parsed and converted to IR, it can run -/// in two contexts: interpreted by LLDB as a DWARF location expression, -/// or compiled by the JIT and inserted into the target process for -/// execution. -/// -/// IRForTarget makes the second possible, by applying a series of -/// transformations to the IR which make it relocatable. These -/// transformations are discussed in more detail next to their relevant -/// functions. -//---------------------------------------------------------------------- -class IRForTarget : public llvm::ModulePass -{ -public: - enum class LookupResult { - Success, - Fail, - Ignore - }; - - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] decl_map - /// The list of externally-referenced variables for the expression, - /// for use in looking up globals and allocating the argument - /// struct. See the documentation for ClangExpressionDeclMap. - /// - /// @param[in] resolve_vars - /// True if the external variable references (including persistent - /// variables) should be resolved. If not, only external functions - /// are resolved. - /// - /// @param[in] execution_policy - /// Determines whether an IR interpreter can be used to statically - /// evaluate the expression. - /// - /// @param[in] const_result - /// This variable is populated with the statically-computed result - /// of the function, if it has no side-effects and the result can - /// be computed statically. - /// - /// @param[in] execution_unit - /// The holder for raw data associated with the expression. - /// - /// @param[in] error_stream - /// If non-NULL, a stream on which errors can be printed. - /// - /// @param[in] func_name - /// The name of the function to prepare for execution in the target. - //------------------------------------------------------------------ - IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, - bool resolve_vars, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Stream *error_stream, - const char* func_name = "$__lldb_expr"); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual ~IRForTarget(); - - //------------------------------------------------------------------ - /// Run this IR transformer on a single module - /// - /// Implementation of the llvm::ModulePass::runOnModule() function. - /// - /// @param[in] llvm_module - /// The module to run on. This module is searched for the function - /// $__lldb_expr, and that function is passed to the passes one by - /// one. - /// - /// @param[in] interpreter_error - /// An error. If the expression fails to be interpreted, this error - /// is set to a reason why. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - virtual bool - runOnModule (llvm::Module &llvm_module); - - //------------------------------------------------------------------ - /// Interface stub - /// - /// Implementation of the llvm::ModulePass::assignPassManager() - /// function. - //------------------------------------------------------------------ - virtual void - assignPassManager (llvm::PMStack &pass_mgr_stack, - llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager); - - //------------------------------------------------------------------ - /// Returns PMT_ModulePassManager - /// - /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() - /// function. - //------------------------------------------------------------------ - virtual llvm::PassManagerType - getPotentialPassManagerType() const; - -private: - //------------------------------------------------------------------ - /// Ensures that the current function's linkage is set to external. - /// Otherwise the JIT may not return an address for it. - /// - /// @param[in] llvm_function - /// The function whose linkage is to be fixed. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - FixFunctionLinkage (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A module-level pass to replace all function pointers with their - /// integer equivalents. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_module - /// The module currently being processed. - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise. - //------------------------------------------------------------------ - bool - HasSideEffects (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A function-level pass to check whether the function has side - /// effects. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Get the address of a function, and a location to put the complete - /// Value of the function if one is available. - /// - /// @param[in] function - /// The function to find the location of. - /// - /// @param[out] ptr - /// The location of the function in the target. - /// - /// @param[out] name - /// The resolved name of the function (matters for intrinsics). - /// - /// @param[out] value_ptr - /// A variable to put the function's completed Value* in, or NULL - /// if the Value* shouldn't be stored anywhere. - /// - /// @return - /// The pointer. - //------------------------------------------------------------------ - LookupResult - GetFunctionAddress (llvm::Function *function, - uint64_t &ptr, - lldb_private::ConstString &name, - llvm::Constant **&value_ptr); - - //------------------------------------------------------------------ - /// Build a function pointer given a type and a raw pointer. - /// - /// @param[in] type - /// The type of the function pointer to be built. - /// - /// @param[in] ptr - /// The value of the pointer. - /// - /// @return - /// The pointer. - //------------------------------------------------------------------ - llvm::Constant * - BuildFunctionPointer (llvm::Type *type, - uint64_t ptr); - - void - RegisterFunctionMetadata (llvm::LLVMContext &context, - llvm::Value *function_ptr, - const char *name); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True if the function has side effects (or if this cannot - /// be determined); false otherwise. - //------------------------------------------------------------------ - bool - ResolveFunctionPointers (llvm::Module &llvm_module); - - //------------------------------------------------------------------ - /// A function-level pass to take the generated global value - /// $__lldb_expr_result and make it into a persistent variable. - /// Also see ASTResultSynthesizer. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Find the NamedDecl corresponding to a Value. This interface is - /// exposed for the IR interpreter. - /// - /// @param[in] module - /// The module containing metadata to search - /// - /// @param[in] global - /// The global entity to search for - /// - /// @return - /// The corresponding variable declaration - //------------------------------------------------------------------ -public: - static clang::NamedDecl * - DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); -private: - clang::NamedDecl * - DeclForGlobal (llvm::GlobalValue *global); - - //------------------------------------------------------------------ - /// Set the constant result variable m_const_result to the provided - /// constant, assuming it can be evaluated. The result variable - /// will be reset to NULL later if the expression has side effects. - /// - /// @param[in] initializer - /// The constant initializer for the variable. - /// - /// @param[in] name - /// The name of the result variable. - /// - /// @param[in] type - /// The Clang type of the result variable. - //------------------------------------------------------------------ - void - MaybeSetConstantResult (llvm::Constant *initializer, - const lldb_private::ConstString &name, - lldb_private::TypeFromParser type); - - //------------------------------------------------------------------ - /// If the IR represents a cast of a variable, set m_const_result - /// to the result of the cast. The result variable will be reset to - /// NULL latger if the expression has side effects. - /// - /// @param[in] type - /// The Clang type of the result variable. - //------------------------------------------------------------------ - void - MaybeSetCastResult (lldb_private::TypeFromParser type); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - CreateResultVariable (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A module-level pass to find Objective-C constant strings and - /// transform them to calls to CFStringCreateWithBytes. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Rewrite a single Objective-C constant string. - /// - /// @param[in] NSStr - /// The constant NSString to be transformed - /// - /// @param[in] CStr - /// The constant C string inside the NSString. This will be - /// passed as the bytes argument to CFStringCreateWithBytes. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCConstString (llvm::GlobalVariable *NSStr, - llvm::GlobalVariable *CStr); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCConstStrings (); - - //------------------------------------------------------------------ - /// A basic block-level pass to find all Objective-C method calls and - /// rewrite them to use sel_registerName instead of statically allocated - /// selectors. The reason is that the selectors are created on the - /// assumption that the Objective-C runtime will scan the appropriate - /// section and prepare them. This doesn't happen when code is copied - /// into the target, though, and there's no easy way to induce the - /// runtime to scan them. So instead we get our selectors from - /// sel_registerName. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Replace a single selector reference - /// - /// @param[in] selector_load - /// The load of the statically-allocated selector. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCSelector (llvm::Instruction* selector_load); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewriteObjCSelectors (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A basic block-level pass to find all newly-declared persistent - /// variables and register them with the ClangExprDeclMap. This - /// allows them to be materialized and dematerialized like normal - /// external variables. Before transformation, these persistent - /// variables look like normal locals, so they have an allocation. - /// This pass excises these allocations and makes references look - /// like external references where they will be resolved -- like all - /// other external references -- by ResolveExternals(). - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Handle a single allocation of a persistent variable - /// - /// @param[in] persistent_alloc - /// The allocation of the persistent variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RewritePersistentAlloc (llvm::Instruction *persistent_alloc); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - //------------------------------------------------------------------ - bool - RewritePersistentAllocs (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A function-level pass to find all external variables and functions - /// used in the IR. Each found external variable is added to the - /// struct, and each external function is resolved in place, its call - /// replaced with a call to a function pointer whose value is the - /// address of the function in the target process. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Write an initializer to a memory array of assumed sufficient - /// size. - /// - /// @param[in] data - /// A pointer to the data to write to. - /// - /// @param[in] initializer - /// The initializer itself. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); - - //------------------------------------------------------------------ - /// Move an internal variable into the static allocation section. - /// - /// @param[in] global_variable - /// The variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaterializeInternalVariable (llvm::GlobalVariable *global_variable); - - //------------------------------------------------------------------ - /// Handle a single externally-defined variable - /// - /// @param[in] value - /// The variable. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaybeHandleVariable (llvm::Value *value); - - //------------------------------------------------------------------ - /// Handle a single externally-defined symbol - /// - /// @param[in] symbol - /// The symbol. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - HandleSymbol (llvm::Value *symbol); - - //------------------------------------------------------------------ - /// Handle a single externally-defined Objective-C class - /// - /// @param[in] classlist_reference - /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" - /// where n (if present) is an index. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - HandleObjCClass(llvm::Value *classlist_reference); - - //------------------------------------------------------------------ - /// Handle all the arguments to a function call - /// - /// @param[in] C - /// The call instruction. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - MaybeHandleCallArguments (llvm::CallInst *call_inst); - - //------------------------------------------------------------------ - /// Resolve variable references in calls to external functions - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ResolveCalls (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// Remove calls to __cxa_atexit, which should never be generated by - /// expressions. - /// - /// @param[in] call_inst - /// The call instruction. - /// - /// @return - /// True if the scan was successful; false if some operation - /// failed - //------------------------------------------------------------------ - bool - RemoveCXAAtExit (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ResolveExternals (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A basic block-level pass to excise guard variables from the code. - /// The result for the function is passed through Clang as a static - /// variable. Static variables normally have guard variables to - /// ensure that they are only initialized once. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// Rewrite a load to a guard variable to return constant 0. - /// - /// @param[in] guard_load - /// The load instruction to zero out. - //------------------------------------------------------------------ - void - TurnGuardLoadIntoZero(llvm::Instruction* guard_load); - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - RemoveGuards (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A module-level pass to allocate all string literals in a separate - /// allocation and redirect references to them. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ReplaceStrings (); - - //------------------------------------------------------------------ - /// A basic block-level pass to find all literals that will be - /// allocated as statics by the JIT (in contrast to the Strings, - /// which already are statics) and synthesize loads for them. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] basic_block - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ReplaceStaticLiterals (llvm::BasicBlock &basic_block); - - //------------------------------------------------------------------ - /// A function-level pass to make all external variable references - /// point at the correct offsets from the void* passed into the - /// function. ClangExpressionDeclMap::DoStructLayout() must be called - /// beforehand, so that the offsets are valid. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - ReplaceVariables (llvm::Function &llvm_function); - - //------------------------------------------------------------------ - /// A module-level pass to remove all global variables from the - /// module since it no longer should export or import any symbols. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] llvm_module - /// The module currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - StripAllGVs (llvm::Module &llvm_module); - - class StaticDataAllocator { - public: - StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); - lldb_private::StreamString &GetStream() - { - return m_stream_string; - } - lldb::addr_t Allocate(); - - lldb::TargetSP - GetTarget(); - private: - lldb_private::IRExecutionUnit &m_execution_unit; - lldb_private::StreamString m_stream_string; - lldb::addr_t m_allocation; - }; - - /// Flags - bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved - std::string m_func_name; ///< The name of the function to translate - lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) - lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. - llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. - std::unique_ptr m_target_data; ///< The target data for the module being processed, or NULL if there is no module. - lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls - StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings - llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type - llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type - llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. - lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed - - llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. - bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) - - llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. - - //------------------------------------------------------------------ - /// UnfoldConstant operates on a constant [Old] which has just been - /// replaced with a value [New]. We assume that new_value has - /// been properly placed early in the function, in front of the - /// first instruction in the entry basic block - /// [FirstEntryInstruction]. - /// - /// UnfoldConstant reads through the uses of Old and replaces Old - /// in those uses with New. Where those uses are constants, the - /// function generates new instructions to compute the result of the - /// new, non-constant expression and places them before - /// FirstEntryInstruction. These instructions replace the constant - /// uses, so UnfoldConstant calls itself recursively for those. - /// - /// @param[in] llvm_function - /// The function currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - - class FunctionValueCache { - public: - typedef std::function Maker; - - FunctionValueCache (Maker const &maker); - ~FunctionValueCache (); - llvm::Value *GetValue (llvm::Function *function); - private: - Maker const m_maker; - typedef std::map FunctionValueMap; - FunctionValueMap m_values; - }; - - FunctionValueCache m_entry_instruction_finder; - - static bool - UnfoldConstant (llvm::Constant *old_constant, - FunctionValueCache &value_maker, - FunctionValueCache &entry_instruction_finder); - - //------------------------------------------------------------------ - /// Construct a reference to m_reloc_placeholder with a given type - /// and offset. This typically happens after inserting data into - /// m_data_allocator. - /// - /// @param[in] type - /// The type of the value being loaded. - /// - /// @param[in] offset - /// The offset of the value from the base of m_data_allocator. - /// - /// @return - /// The Constant for the reference, usually a ConstantExpr. - //------------------------------------------------------------------ - llvm::Constant * - BuildRelocation(llvm::Type *type, - uint64_t offset); - - //------------------------------------------------------------------ - /// Commit the allocation in m_data_allocator and use its final - /// location to replace m_reloc_placeholder. - /// - /// @param[in] module - /// The module that m_data_allocator resides in - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool - CompleteDataAllocation (); - -}; - -#endif diff --git a/include/lldb/Expression/IRInterpreter.h b/include/lldb/Expression/IRInterpreter.h index c314bf1099ea..4eb81bc68d19 100644 --- a/include/lldb/Expression/IRInterpreter.h +++ b/include/lldb/Expression/IRInterpreter.h @@ -13,7 +13,6 @@ #include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/TaggedASTType.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Pass.h" diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h index 80add46ef0da..6fb718a341f7 100644 --- a/include/lldb/Expression/IRMemoryMap.h +++ b/include/lldb/Expression/IRMemoryMap.h @@ -50,7 +50,12 @@ public: eAllocationPolicyProcessOnly ///< The intent is that this allocation exist only in the process. }; - lldb::addr_t Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error); + lldb::addr_t Malloc (size_t size, + uint8_t alignment, + uint32_t permissions, + AllocationPolicy policy, + bool zero_memory, + Error &error); void Leak (lldb::addr_t process_address, Error &error); void Free (lldb::addr_t process_address, Error &error); @@ -124,7 +129,7 @@ private: typedef std::map AllocationMap; AllocationMap m_allocations; - lldb::addr_t FindSpace (size_t size); + lldb::addr_t FindSpace (size_t size, bool zero_memory = false); bool ContainsHostOnlyAllocations (); AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size); diff --git a/include/lldb/Expression/IRToDWARF.h b/include/lldb/Expression/IRToDWARF.h deleted file mode 100644 index a4ae9b7ebfae..000000000000 --- a/include/lldb/Expression/IRToDWARF.h +++ /dev/null @@ -1,111 +0,0 @@ -//===-- IRToDWARF.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_IRToDWARF_h_ -#define liblldb_IRToDWARF_h_ - -#include "llvm/Pass.h" -#include "llvm/IR/LegacyPassManager.h" - -#include "lldb/lldb-public.h" - -class Relocator; -//---------------------------------------------------------------------- -/// @class IRToDWARF IRToDWARF.h "lldb/Expression/IRToDWARF.h" -/// @brief Transforms the IR for a function into a DWARF location expression -/// -/// Once an expression has been parsed and converted to IR, it can run -/// in two contexts: interpreted by LLDB as a DWARF location expression, -/// or compiled by the JIT and inserted into the target process for -/// execution. -/// -/// IRToDWARF makes the first possible, by traversing the control flow -/// graph and writing the code for each basic block out as location -/// expression bytecode. To ensure that the links between the basic blocks -/// remain intact, it uses a relocator that records the location of every -/// location expression instruction that has a relocatable operand, the -/// target of that operand (as a basic block), and the mapping of each basic -/// block to an actual location. After all code has been written out, the -/// relocator post-processes it and performs all necessary relocations. -//---------------------------------------------------------------------- -class IRToDWARF : public llvm::ModulePass -{ -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] local_vars - /// A list of variables to populate with the local variables this - /// expression uses. - /// - /// @param[in] decl_map - /// The list of externally-referenced variables for the expression, - /// for use in looking up globals. - /// - /// @param[in] stream - /// The stream to dump DWARF bytecode onto. - /// - /// @param[in] func_name - /// The name of the function to translate to DWARF. - //------------------------------------------------------------------ - IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars, - lldb_private::ClangExpressionDeclMap *decl_map, - lldb_private::StreamString &strm, - const char* func_name = "$__lldb_expr"); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual ~IRToDWARF(); - - //------------------------------------------------------------------ - /// Run this IR transformer on a single module - /// - /// @param[in] M - /// The module to run on. This module is searched for the function - /// $__lldb_expr, and that function is converted to a location - /// expression. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool runOnModule(llvm::Module &M); - - //------------------------------------------------------------------ - /// Interface stub - //------------------------------------------------------------------ - void assignPassManager(llvm::PMStack &PMS, - llvm::PassManagerType T = llvm::PMT_ModulePassManager); - - //------------------------------------------------------------------ - /// Returns PMT_ModulePassManager - //------------------------------------------------------------------ - llvm::PassManagerType getPotentialPassManagerType() const; -private: - //------------------------------------------------------------------ - /// Run this IR transformer on a single basic block - /// - /// @param[in] BB - /// The basic block to transform. - /// - /// @param[in] Relocator - /// The relocator to use when registering branches. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool runOnBasicBlock(llvm::BasicBlock &BB, Relocator &Relocator); - - std::string m_func_name; ///< The name of the function to translate - lldb_private::ClangExpressionVariableList &m_local_vars; ///< The list of local variables to populate while transforming - lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The list of external variables - lldb_private::StreamString &m_strm; ///< The stream to write bytecode to -}; - -#endif diff --git a/include/lldb/Expression/LLVMUserExpression.h b/include/lldb/Expression/LLVMUserExpression.h new file mode 100644 index 000000000000..e3d17986f4b3 --- /dev/null +++ b/include/lldb/Expression/LLVMUserExpression.h @@ -0,0 +1,118 @@ +//===-- LLVMUserExpression.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_LLVMUserExpression_h +#define liblldb_LLVMUserExpression_h + +// C Includes +// C++ Includes +#include +#include +#include + +// Project includes +#include "lldb/Expression/UserExpression.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class LLVMUserExpression LLVMUserExpression.h "lldb/Expression/LLVMUserExpression.h" +/// @brief Encapsulates a one-time expression for use in lldb. +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. LLVMUserExpression is a virtual base +/// class that encapsulates the objects needed to parse and JIT an expression. +/// The actual parsing part will be provided by the specific implementations +/// of LLVMUserExpression - which will be vended through the appropriate TypeSystem. +//---------------------------------------------------------------------- +class LLVMUserExpression : public UserExpression +{ + public: + LLVMUserExpression(ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options); + ~LLVMUserExpression() override; + + lldb::ExpressionResults Execute(Stream &error_stream, + ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; + + bool FinalizeJITExecution(Stream &error_stream, + 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; + + bool + CanInterpret() override + { + return m_can_interpret; + } + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text() override + { + return m_transformed_text.c_str(); + } + + lldb::ModuleSP GetJITModule() override; + + protected: + virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; + + bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address); + + virtual bool + AddArguments (ExecutionContext &exe_ctx, + std::vector &args, + lldb::addr_t struct_address, + Stream &error_stream) = 0; + + + lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame. + lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame. + + bool m_allow_cxx; ///< True if the language allows C++. + bool m_allow_objc; ///< True if the language allows Objective-C. + std::string m_transformed_text; ///< The text of the expression, as send to the parser + + std::shared_ptr m_execution_unit_sp; ///< The execution unit the expression is stored in. + std::unique_ptr m_materializer_ap; ///< The materializer to use when running the expression. + lldb::ModuleWP m_jit_module_wp; + bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer + ///in order to generate the expression as a method. + bool m_in_cplusplus_method; ///< True if the expression is compiled as a C++ member function (true if it was parsed + ///when exe_ctx was in a C++ method). + bool m_in_objectivec_method; ///< True if the expression is compiled as an Objective-C method (true if it was parsed + ///when exe_ctx was in an Objective-C method). + bool m_in_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it + ///was parsed when exe_ctx was in an Objective-C class method). + bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression + ///doesn't really use them and they can be NULL. + bool m_const_object; ///< True if "this" is const. + Target *m_target; ///< The target for storing persistent data like types and variables. + + bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise. + lldb::addr_t + m_materialized_address; ///< The address at which the arguments to the expression have been materialized. + Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer. +}; + +} // namespace lldb_private +#endif diff --git a/include/lldb/Expression/Materializer.h b/include/lldb/Expression/Materializer.h index 208a08133923..f293fddc1022 100644 --- a/include/lldb/Expression/Materializer.h +++ b/include/lldb/Expression/Materializer.h @@ -7,18 +7,22 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_Materializer_h -#define lldb_Materializer_h +#ifndef liblldb_Materializer_h +#define liblldb_Materializer_h +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private-types.h" #include "lldb/Core/Error.h" #include "lldb/Expression/IRMemoryMap.h" -#include "lldb/Host/Mutex.h" -#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/StackFrame.h" -#include - namespace lldb_private { @@ -32,8 +36,8 @@ public: { public: Dematerializer () : - m_materializer(NULL), - m_map(NULL), + m_materializer(nullptr), + m_map(nullptr), m_process_address(LLDB_INVALID_ADDRESS) { } @@ -44,7 +48,6 @@ public: } void Dematerialize (Error &err, - lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_top, lldb::addr_t frame_bottom); @@ -54,6 +57,7 @@ public: { return m_materializer && m_map && (m_process_address != LLDB_INVALID_ADDRESS); } + private: friend class Materializer; @@ -84,11 +88,28 @@ public: DematerializerSP Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err); - uint32_t AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err); - uint32_t AddVariable (lldb::VariableSP &variable_sp, Error &err); - uint32_t AddResultVariable (const TypeFromUser &type, bool is_lvalue, bool keep_in_memory, Error &err); - uint32_t AddSymbol (const Symbol &symbol_sp, Error &err); - uint32_t AddRegister (const RegisterInfo ®ister_info, Error &err); + class PersistentVariableDelegate + { + public: + virtual ~PersistentVariableDelegate(); + virtual ConstString GetName() = 0; + virtual void DidDematerialize(lldb::ExpressionVariableSP &variable) = 0; + }; + + uint32_t AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp, + PersistentVariableDelegate *delegate, + Error &err); + uint32_t AddVariable (lldb::VariableSP &variable_sp, + Error &err); + uint32_t AddResultVariable (const CompilerType &type, + bool is_lvalue, + bool keep_in_memory, + PersistentVariableDelegate *delegate, + Error &err); + uint32_t AddSymbol (const Symbol &symbol_sp, + Error &err); + uint32_t AddRegister (const RegisterInfo ®ister_info, + Error &err); uint32_t GetStructAlignment () { @@ -100,14 +121,6 @@ public: return m_current_offset; } - uint32_t GetResultOffset () - { - if (m_result_entity) - return m_result_entity->GetOffset(); - else - return UINT32_MAX; - } - class Entity { public: @@ -117,11 +130,9 @@ public: m_offset(0) { } - - virtual ~Entity () - { - } - + + virtual ~Entity() = default; + virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0; virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err) = 0; @@ -147,8 +158,9 @@ public: { m_offset = offset; } + protected: - void SetSizeAndAlignmentFromType (ClangASTType &type); + void SetSizeAndAlignmentFromType (CompilerType &type); uint32_t m_alignment; uint32_t m_size; @@ -163,11 +175,10 @@ private: DematerializerWP m_dematerializer_wp; EntityVector m_entities; - Entity *m_result_entity; uint32_t m_current_offset; uint32_t m_struct_alignment; }; -} +} // namespace lldb_private -#endif +#endif // liblldb_Materializer_h diff --git a/include/lldb/Expression/REPL.h b/include/lldb/Expression/REPL.h new file mode 100644 index 000000000000..21d22de8e0d7 --- /dev/null +++ b/include/lldb/Expression/REPL.h @@ -0,0 +1,211 @@ +//===-- REPL.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_REPL_h +#define lldb_REPL_h + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/../../source/Commands/CommandObjectExpression.h" + +namespace lldb_private +{ + +class REPL : public IOHandlerDelegate +{ +public: + //---------------------------------------------------------------------- + // See TypeSystem.h for how to add subclasses to this. + //---------------------------------------------------------------------- + enum LLVMCastKind { + eKindClang, + eKindSwift, + eKindGo, + kNumKinds + }; + + LLVMCastKind getKind() const { return m_kind; } + + REPL(LLVMCastKind kind, Target &target); + + ~REPL() override; + + //------------------------------------------------------------------ + /// Get a REPL with an existing target (or, failing that, a debugger to use), and (optional) extra arguments for the compiler. + /// + /// @param[out] error + /// If this language is supported but the REPL couldn't be created, this error is populated with the reason. + /// + /// @param[in] language + /// The language to create a REPL for. + /// + /// @param[in] debugger + /// If provided, and target is nullptr, the debugger to use when setting up a top-level REPL. + /// + /// @param[in] target + /// If provided, the target to put the REPL inside. + /// + /// @param[in] repl_options + /// If provided, additional options for the compiler when parsing REPL expressions. + /// + /// @return + /// The range of the containing object in the target process. + //------------------------------------------------------------------ + static lldb::REPLSP + Create (Error &Error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options); + + void + SetFormatOptions (const OptionGroupFormat &options) + { + m_format_options = options; + } + + void + SetValueObjectDisplayOptions (const OptionGroupValueObjectDisplay &options) + { + m_varobj_options = options; + } + + void + SetCommandOptions (const CommandObjectExpression::CommandOptions &options) + { + m_command_options = options; + } + + void + SetCompilerOptions (const char *options) + { + if (options) + m_compiler_options = options; + } + + lldb::IOHandlerSP + GetIOHandler (); + + Error + RunLoop (); + + //------------------------------------------------------------------ + // IOHandler::Delegate functions + //------------------------------------------------------------------ + void + IOHandlerActivated (IOHandler &io_handler) override; + + bool + IOHandlerInterrupt (IOHandler &io_handler) override; + + void + IOHandlerInputInterrupted (IOHandler &io_handler, + std::string &line) override; + + const char * + IOHandlerGetFixIndentationCharacters () override; + + ConstString + IOHandlerGetControlSequence (char ch) override; + + const char * + IOHandlerGetCommandPrefix () override; + + const char * + IOHandlerGetHelpPrologue () override; + + bool + IOHandlerIsInputComplete (IOHandler &io_handler, + StringList &lines) override; + + int + IOHandlerFixIndentation (IOHandler &io_handler, + const StringList &lines, + int cursor_position) override; + + void + IOHandlerInputComplete (IOHandler &io_handler, + std::string &line) override; + + 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; + +protected: + static int + CalculateActualIndentation (const StringList &lines); + + //---------------------------------------------------------------------- + // Subclasses should override these functions to implement a functional REPL. + //---------------------------------------------------------------------- + + virtual Error + DoInitialization () = 0; + + virtual ConstString + GetSourceFileBasename () = 0; + + virtual const char * + GetAutoIndentCharacters () = 0; + + virtual bool + SourceIsComplete (const std::string &source) = 0; + + virtual lldb::offset_t + GetDesiredIndentation (const StringList &lines, + int cursor_position, + int tab_size) = 0; // LLDB_INVALID_OFFSET means no change + + virtual lldb::LanguageType + GetLanguage () = 0; + + virtual bool + PrintOneVariable (Debugger &debugger, + lldb::StreamFileSP &output_sp, + lldb::ValueObjectSP &valobj_sp, + ExpressionVariable *var = nullptr) = 0; + + virtual int + CompleteCode(const std::string ¤t_code, + StringList &matches) = 0; + + OptionGroupFormat m_format_options = OptionGroupFormat(lldb::eFormatDefault); + OptionGroupValueObjectDisplay m_varobj_options; + CommandObjectExpression::CommandOptions m_command_options; + std::string m_compiler_options; + + bool m_enable_auto_indent = true; + std::string m_indent_str; // Use this string for each level of indentation + std::string m_current_indent_str; + uint32_t m_current_indent_level = 0; + + std::string m_repl_source_path; + bool m_dedicated_repl_mode = false; + + StringList m_code; // All accumulated REPL statements are saved here + + Target &m_target; + lldb::IOHandlerSP m_io_handler_sp; + LLVMCastKind m_kind; + +private: + std::string + GetSourcePath(); +}; + +} // namespace lldb_private + +#endif // lldb_REPL_h diff --git a/include/lldb/Expression/UserExpression.h b/include/lldb/Expression/UserExpression.h new file mode 100644 index 000000000000..517dfcd1dc47 --- /dev/null +++ b/include/lldb/Expression/UserExpression.h @@ -0,0 +1,335 @@ +//===-- UserExpression.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_UserExpression_h_ +#define liblldb_UserExpression_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Expression/Expression.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h" +/// @brief Encapsulates a one-time expression for use in lldb. +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. UserExpression is a virtual base +/// class that encapsulates the objects needed to parse and interpret or +/// JIT an expression. The actual parsing part will be provided by the specific +/// implementations of UserExpression - which will be vended through the +/// appropriate TypeSystem. +//---------------------------------------------------------------------- +class UserExpression : public Expression +{ +public: + enum { kDefaultTimeout = 500000u }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-nullptr, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + UserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~UserExpression() override; + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + virtual bool + Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) = 0; + + virtual bool CanInterpret() = 0; + + bool + MatchesContext (ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Execute the parsed expression + /// + /// @param[in] error_stream + /// A stream to print errors to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of variables, etc.) + /// + /// @param[in] options + /// Expression evaluation options. + /// + /// @param[in] shared_ptr_to_me + /// This is a shared pointer to this UserExpression. This is + /// needed because Execute can push a thread plan that will hold onto + /// the UserExpression for an unbounded period of time. So you + /// need to give the thread plan a reference to this object that can + /// keep it alive. + /// + /// @param[in] result + /// A pointer to direct at the persistent variable in which the + /// expression's result is stored. + /// + /// @return + /// A Process::Execution results value. + //------------------------------------------------------------------ + virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) = 0; + + //------------------------------------------------------------------ + /// Apply the side effects of the function to program state. + /// + /// @param[in] error_stream + /// A stream to print errors to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of variables, etc.) + /// + /// @param[in] result + /// A pointer to direct at the persistent variable in which the + /// expression's result is stored. + /// + /// @param[in] function_stack_pointer + /// A pointer to the base of the function's stack frame. This + /// is used to determine whether the expression result resides in + /// memory that will still be valid, or whether it needs to be + /// treated as homeless for the purpose of future expressions. + /// + /// @return + /// A Process::Execution results value. + //------------------------------------------------------------------ + virtual bool FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, + lldb::ExpressionVariableSP &result, + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0; + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. + //------------------------------------------------------------------ + const char * + Text() override + { + return m_expr_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the string that the user typed. + //------------------------------------------------------------------ + const char * + GetUserText () + { + return m_expr_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName() override + { + return "$__lldb_expr"; + } + + //------------------------------------------------------------------ + /// Return the language that should be used when parsing. To use + /// the default, return eLanguageTypeUnknown. + //------------------------------------------------------------------ + lldb::LanguageType + Language() override + { + return m_language; + } + + //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + ResultType + DesiredResultType() override + { + return m_desired_type; + } + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation() override + { + return true; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution() override + { + return true; + } + + EvaluateExpressionOptions * + GetOptions() override + { + return &m_options; + } + + virtual lldb::ExpressionVariableSP + GetResultAfterDematerialization(ExecutionContextScope *exe_scope) + { + return lldb::ExpressionVariableSP(); + } + + virtual lldb::ModuleSP + GetJITModule() + { + return lldb::ModuleSP(); + } + + //------------------------------------------------------------------ + /// Evaluate one expression in the scratch context of the + /// target passed in the exe_ctx and return its result. + /// + /// @param[in] exe_ctx + /// The execution context to use when evaluating the expression. + /// + /// @param[in] options + /// Expression evaluation options. N.B. The language in the + /// evaluation options will be used to determine the language used for + /// expression evaluation. + /// + /// @param[in] expr_cstr + /// A C string containing the expression to be evaluated. + /// + /// @param[in] expr_prefix + /// If non-nullptr, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in,out] result_valobj_sp + /// If execution is successful, the result valobj is placed here. + /// + /// @param[out] error + /// Filled in with an error in case the expression evaluation + /// fails to parse, run, or evaluated. + /// + /// @param[in] line_offset + /// The offset of the first line of the expression from the "beginning" of a virtual source file used for error reporting and debug info. + /// + /// @param[out] jit_module_sp_ptr + /// If non-nullptr, used to persist the generated IR module. + /// + /// @result + /// A Process::ExpressionResults value. eExpressionCompleted for success. + //------------------------------------------------------------------ + static lldb::ExpressionResults + Evaluate(ExecutionContext &exe_ctx, + const EvaluateExpressionOptions& options, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + Error &error, + uint32_t line_offset = 0, + lldb::ModuleSP *jit_module_sp_ptr = nullptr); + + static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. + +protected: + static lldb::addr_t + GetObjectPointer (lldb::StackFrameSP frame_sp, + ConstString &object_name, + Error &err); + + //------------------------------------------------------------------ + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. + //------------------------------------------------------------------ + + void + InstallContext (ExecutionContext &exe_ctx); + + bool + LockAndCheckContext (ExecutionContext &exe_ctx, + lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::StackFrameSP &frame_sp); + + Address m_address; ///< The address the process is stopped in. + std::string m_expr_text; ///< The text of the expression, as typed by the user + std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user + lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults) + ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression. + EvaluateExpressionOptions m_options; ///< Additional options provided by the user. +}; + +} // namespace lldb_private + +#endif // liblldb_UserExpression_h_ diff --git a/include/lldb/Expression/UtilityFunction.h b/include/lldb/Expression/UtilityFunction.h new file mode 100644 index 000000000000..bee83d8111e4 --- /dev/null +++ b/include/lldb/Expression/UtilityFunction.h @@ -0,0 +1,162 @@ +//===-- UtilityFunction.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_UtilityFunction_h_ +#define liblldb_UtilityFunction_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Expression/Expression.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class UtilityFunction UtilityFunction.h "lldb/Expression/UtilityFunction.h" +/// @brief Encapsulates a bit of source code that provides a function that is callable +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. UtilityFunction encapsulates +/// a self-contained function meant to be used from other code. Utility +/// functions can perform error-checking for ClangUserExpressions, +//---------------------------------------------------------------------- +class UtilityFunction : public Expression +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + UtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name); + + ~UtilityFunction() override; + + //------------------------------------------------------------------ + /// Install the utility function into a process + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to install the utility function to. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + virtual bool + Install (Stream &error_stream, ExecutionContext &exe_ctx) = 0; + + //------------------------------------------------------------------ + /// Check whether the given PC is inside the function + /// + /// Especially useful if the function dereferences nullptr to indicate a failed + /// assert. + /// + /// @param[in] pc + /// The program counter to check. + /// + /// @return + /// True if the program counter falls within the function's bounds; + /// false if not (or the function is not JIT compiled) + //------------------------------------------------------------------ + bool + ContainsAddress (lldb::addr_t address) + { + // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, + // so this always returns false if the function is not JIT compiled yet + return (address >= m_jit_start_addr && address < m_jit_end_addr); + } + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text() override + { + return m_function_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName() override + { + return m_function_name.c_str(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when registering + /// local variables. May be nullptr if the Expression doesn't care. + //------------------------------------------------------------------ + ExpressionVariableList * + LocalVariables () + { + return nullptr; + } + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation() override + { + return false; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution() override + { + return false; + } + + // This makes the function caller function. + FunctionCaller * + MakeFunctionCaller(const CompilerType &return_type, const ValueList &arg_value_list, Error &error); + + // This one retrieves the function caller that is already made. If you haven't made it yet, this returns nullptr + FunctionCaller * + GetFunctionCaller() + { + return m_caller_up.get(); + } + +protected: + std::shared_ptr m_execution_unit_sp; + lldb::ModuleWP m_jit_module_wp; + std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit. + std::string m_function_name; ///< The name of the function. + std::unique_ptr m_caller_up; +}; + +} // namespace lldb_private + +#endif // liblldb_UtilityFunction_h_ diff --git a/include/lldb/Host/Condition.h b/include/lldb/Host/Condition.h index 7431315c37a0..bd793c65e0f4 100644 --- a/include/lldb/Host/Condition.h +++ b/include/lldb/Host/Condition.h @@ -7,11 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DBCondition_h_ -#define liblldb_DBCondition_h_ -#if defined(__cplusplus) - +#ifndef liblldb_Condition_h_ +#define liblldb_Condition_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-types.h" #include "lldb/Host/Mutex.h" @@ -31,7 +33,6 @@ class TimeValue; class Condition { public: - //------------------------------------------------------------------ /// Default constructor /// @@ -73,9 +74,9 @@ public: /// \a mutex. The waiting thread unblocks only after another thread /// signals or broadcasts this object's condition variable. /// - /// If \a abstime is non-NULL, this function will return when the + /// If \a abstime is non-nullptr, this function will return when the /// system time reaches the time specified in \a abstime if the - /// condition variable doesn't get unblocked. If \a abstime is NULL + /// condition variable doesn't get unblocked. If \a abstime is nullptr /// this function will wait for an infinite amount of time for the /// condition variable to be unblocked. /// @@ -87,19 +88,19 @@ public: /// \c pthread_cond_wait() calls. /// /// @param[in] abstime - /// An absolute time at which to stop waiting if non-NULL, else + /// An absolute time at which to stop waiting if non-nullptr, else /// wait an infinite amount of time for the condition variable /// toget signaled. /// /// @param[out] timed_out - /// If not NULL, will be set to true if the wait timed out, and + /// If not nullptr, will be set to true if the wait timed out, and // false otherwise. /// /// @see Condition::Broadcast() /// @see Condition::Signal() //------------------------------------------------------------------ int - Wait (Mutex &mutex, const TimeValue *abstime = NULL, bool *timed_out = NULL); + Wait(Mutex &mutex, const TimeValue *abstime = nullptr, bool *timed_out = nullptr); protected: //------------------------------------------------------------------ @@ -119,6 +120,4 @@ protected: } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif - +#endif // liblldb_Condition_h_ diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h index 7872eb95aab6..f70f4de0819d 100644 --- a/include/lldb/Host/Config.h +++ b/include/lldb/Host/Config.h @@ -22,10 +22,14 @@ #include "lldb/Host/linux/Config.h" -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) #include "lldb/Host/freebsd/Config.h" +#elif defined(__NetBSD__) + +#include "lldb/Host/netbsd/Config.h" + #elif defined(__MINGW__) || defined (__MINGW32__) #include "lldb/Host/mingw/Config.h" diff --git a/include/lldb/Host/Debug.h b/include/lldb/Host/Debug.h index 87dffb9865c2..7954ee0b6b3f 100644 --- a/include/lldb/Host/Debug.h +++ b/include/lldb/Host/Debug.h @@ -10,7 +10,12 @@ #ifndef liblldb_Debug_h_ #define liblldb_Debug_h_ +// C Includes +// C++ Includes #include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" namespace lldb_private { @@ -59,9 +64,7 @@ namespace lldb_private { } } - ~ResumeActionList() - { - } + ~ResumeActionList() = default; bool IsEmpty() const @@ -114,7 +117,7 @@ namespace lldb_private { } if (default_ok && tid != LLDB_INVALID_THREAD_ID) return GetActionForThread (LLDB_INVALID_THREAD_ID, false); - return NULL; + return nullptr; } size_t @@ -133,7 +136,7 @@ namespace lldb_private { bool SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal) { - if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL) + if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == nullptr) { // There isn't a default action so we do need to set it. ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal }; @@ -203,4 +206,5 @@ namespace lldb_private { } details; }; } -#endif // #ifndef liblldb_Debug_h_ + +#endif // liblldb_Debug_h_ diff --git a/include/lldb/Host/Endian.h b/include/lldb/Host/Endian.h index 1ae3c40b5ca4..df0796b7baf1 100644 --- a/include/lldb/Host/Endian.h +++ b/include/lldb/Host/Endian.h @@ -12,7 +12,7 @@ #include "lldb/lldb-enumerations.h" -namespace lldb { +namespace lldb_private { namespace endian { @@ -22,7 +22,7 @@ namespace endian { uint8_t bytes[sizeof(uint32_t)]; } const endianTest = { 0x01020304 }; - inline ByteOrder InlHostByteOrder() { return (ByteOrder)endianTest.bytes[0]; } + inline lldb::ByteOrder InlHostByteOrder() { return (lldb::ByteOrder)endianTest.bytes[0]; } // ByteOrder const InlHostByteOrder = (ByteOrder)endianTest.bytes[0]; } diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h index 5747cb5adcfd..27f3f405ffd3 100644 --- a/include/lldb/Host/File.h +++ b/include/lldb/Host/File.h @@ -9,12 +9,15 @@ #ifndef liblldb_File_h_ #define liblldb_File_h_ -#if defined(__cplusplus) +// C Includes +// C++ Includes #include #include #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/IOObject.h" @@ -73,13 +76,11 @@ public: File (const File &rhs); - File & - operator= (const File &rhs); //------------------------------------------------------------------ /// Constructor with path. /// /// Takes a path to a file which can be just a filename, or a full - /// path. If \a path is not NULL or empty, this function will call + /// 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 @@ -101,10 +102,10 @@ public: /// Constructor with FileSpec. /// /// Takes a FileSpec pointing to a file which can be just a filename, or a full - /// path. If \a path is not NULL or empty, this function will call + /// 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 + /// @param[in] filespec /// The FileSpec for this file. /// /// @param[in] options @@ -124,7 +125,9 @@ public: m_descriptor (fd), m_stream (kInvalidStream), m_options (0), - m_own_stream (false) + m_own_stream (false), + m_is_interactive (eLazyBoolCalculate), + m_is_real_terminal (eLazyBoolCalculate) { } @@ -133,11 +136,13 @@ public: /// /// The destructor is virtual in case this class is subclassed. //------------------------------------------------------------------ - virtual - ~File (); + ~File() override; + + File & + operator= (const File &rhs); bool - IsValid () const + IsValid() const override { return DescriptorIsValid() || StreamIsValid(); } @@ -156,7 +161,7 @@ public: /// /// @return /// A pointer to this object if either the directory or filename - /// is valid, NULL otherwise. + /// is valid, nullptr otherwise. //------------------------------------------------------------------ operator bool () const @@ -216,7 +221,7 @@ public: uint32_t permissions = lldb::eFilePermissionsFileDefault); Error - Close (); + Close() override; Error Duplicate (const File &rhs); @@ -225,8 +230,7 @@ public: GetDescriptor() const; WaitableHandle - GetWaitableHandle(); - + GetWaitableHandle() override; void SetDescriptor(int fd, bool transfer_ownership); @@ -247,7 +251,7 @@ public: /// @param[in] buf /// A buffer where to put the bytes that are read. /// - /// @param[in/out] num_bytes + /// @param[in,out] num_bytes /// The number of bytes to read form the current file position /// which gets modified with the number of bytes that were read. /// @@ -256,7 +260,7 @@ public: /// failure. //------------------------------------------------------------------ Error - Read (void *buf, size_t &num_bytes); + Read(void *buf, size_t &num_bytes) override; //------------------------------------------------------------------ /// Write bytes to a file at the current file position. @@ -268,7 +272,7 @@ public: /// @param[in] buf /// A buffer where to put the bytes that are read. /// - /// @param[in/out] num_bytes + /// @param[in,out] num_bytes /// The number of bytes to write to the current file position /// which gets modified with the number of bytes that were /// written. @@ -278,7 +282,7 @@ public: /// failure. //------------------------------------------------------------------ Error - Write (const void *buf, size_t &num_bytes); + Write(const void *buf, size_t &num_bytes) override; //------------------------------------------------------------------ /// Seek to an offset relative to the beginning of the file. @@ -295,13 +299,13 @@ public: /// /// @param[in] error_ptr /// A pointer to a lldb_private::Error object that will be - /// filled in if non-NULL. + /// filled in if non-nullptr. /// /// @return /// The resulting seek offset, or -1 on error. //------------------------------------------------------------------ off_t - SeekFromStart (off_t offset, Error *error_ptr = NULL); + SeekFromStart(off_t offset, Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Seek to an offset relative to the current file position. @@ -318,13 +322,13 @@ public: /// /// @param[in] error_ptr /// A pointer to a lldb_private::Error object that will be - /// filled in if non-NULL. + /// filled in if non-nullptr. /// /// @return /// The resulting seek offset, or -1 on error. //------------------------------------------------------------------ off_t - SeekFromCurrent (off_t offset, Error *error_ptr = NULL); + SeekFromCurrent(off_t offset, Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Seek to an offset relative to the end of the file. @@ -335,20 +339,20 @@ public: /// @see File::Read (void *, size_t, off_t &) /// @see File::Write (const void *, size_t, off_t &) /// - /// @param[in/out] offset + /// @param[in,out] offset /// The offset to seek to within the file relative to the /// end of the file which gets filled in with the resulting /// absolute file offset. /// /// @param[in] error_ptr /// A pointer to a lldb_private::Error object that will be - /// filled in if non-NULL. + /// filled in if non-nullptr. /// /// @return /// The resulting seek offset, or -1 on error. //------------------------------------------------------------------ off_t - SeekFromEnd (off_t offset, Error *error_ptr = NULL); + SeekFromEnd(off_t offset, Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Read bytes from a file from the specified file offset. @@ -357,14 +361,14 @@ public: /// own file position markers and reads on other threads won't mess /// up the current read. /// - /// @param[in] buf + /// @param[in] dst /// A buffer where to put the bytes that are read. /// - /// @param[in/out] num_bytes + /// @param[in,out] num_bytes /// The number of bytes to read form the current file position /// which gets modified with the number of bytes that were read. /// - /// @param[in/out] offset + /// @param[in,out] offset /// The offset within the file from which to read \a num_bytes /// bytes. This offset gets incremented by the number of bytes /// that were read. @@ -383,11 +387,11 @@ public: /// own file position markers and reads on other threads won't mess /// up the current read. /// - /// @param[in/out] num_bytes + /// @param[in,out] num_bytes /// The number of bytes to read form the current file position /// which gets modified with the number of bytes that were read. /// - /// @param[in/out] offset + /// @param[in,out] offset /// The offset within the file from which to read \a num_bytes /// bytes. This offset gets incremented by the number of bytes /// that were read. @@ -419,15 +423,15 @@ public: /// their own locking externally to avoid multiple people writing /// to the file at the same time. /// - /// @param[in] buf + /// @param[in] src /// A buffer containing the bytes to write. /// - /// @param[in/out] num_bytes + /// @param[in,out] num_bytes /// The number of bytes to write to the file at offset \a offset. /// \a num_bytes gets modified with the number of bytes that /// were read. /// - /// @param[in/out] offset + /// @param[in,out] offset /// The offset within the file at which to write \a num_bytes /// bytes. This offset gets incremented by the number of bytes /// that were written. @@ -472,7 +476,6 @@ public: static uint32_t GetPermissions(const FileSpec &file_spec, Error &error); - //------------------------------------------------------------------ /// Return true if this file is interactive. /// @@ -497,6 +500,9 @@ public: //------------------------------------------------------------------ bool GetIsRealTerminal (); + + bool + GetIsTerminalWithColors (); //------------------------------------------------------------------ /// Output printf formatted output to the stream. @@ -516,15 +522,13 @@ public: size_t PrintfVarArg(const char *format, va_list args); - void SetOptions (uint32_t options) { m_options = options; } + protected: - - bool DescriptorIsValid () const { @@ -549,9 +553,9 @@ protected: bool m_own_stream; LazyBool m_is_interactive; LazyBool m_is_real_terminal; + LazyBool m_supports_colors; }; } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_File_h_ +#endif // liblldb_File_h_ diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h index d0338d41db1b..0ff1bc9d2f44 100644 --- a/include/lldb/Host/FileSpec.h +++ b/include/lldb/Host/FileSpec.h @@ -9,10 +9,14 @@ #ifndef liblldb_FileSpec_h_ #define liblldb_FileSpec_h_ -#if defined(__cplusplus) +// C Includes +// C++ Includes #include +#include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/STLUtils.h" @@ -66,14 +70,14 @@ public: /// Constructor with path. /// /// Takes a path to a file which can be just a filename, or a full - /// path. If \a path is not NULL or empty, this function will call + /// path. If \a path is not nullptr or empty, this function will call /// FileSpec::SetFile (const char *path, bool resolve). /// /// @param[in] path /// The full or partial path to a file. /// /// @param[in] resolve_path - /// If \b true, then we resolve the path with realpath, + /// 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. /// /// @see FileSpec::SetFile (const char *path, bool resolve) @@ -101,10 +105,10 @@ public: /// Copy constructor /// /// Makes a copy of the uniqued directory and filename strings from - /// \a rhs if it is not NULL. + /// \a rhs if it is not nullptr. /// /// @param[in] rhs - /// A const FileSpec object pointer to copy if non-NULL. + /// A const FileSpec object pointer to copy if non-nullptr. //------------------------------------------------------------------ FileSpec (const FileSpec* rhs); @@ -190,7 +194,7 @@ public: /// /// @return /// A pointer to this object if either the directory or filename - /// is valid, NULL otherwise. + /// is valid, nullptr otherwise. //------------------------------------------------------------------ explicit operator bool() const; @@ -444,7 +448,7 @@ public: /// /// Returns a ConstString that represents the extension of the filename /// for this FileSpec object. If this object does not represent a file, - /// or the filename has no extension, ConstString(NULL) is returned. + /// or the filename has no extension, ConstString(nullptr) is returned. /// The dot ('.') character is not returned as part of the extension /// /// @return @@ -510,10 +514,7 @@ public: } bool - IsSymbolicLink () const - { - return GetFileType() == FileSpec::eFileTypeSymbolicLink; - } + IsSymbolicLink () const; //------------------------------------------------------------------ /// Get the memory cost of this object. @@ -555,13 +556,12 @@ public: /// /// @return /// A shared pointer to the memory mapped data. This shared - /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer can contain a nullptr DataBuffer pointer, so the contained /// pointer must be checked prior to using it. //------------------------------------------------------------------ lldb::DataBufferSP MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const; - //------------------------------------------------------------------ /// Memory map part of, or the entire contents of, a file only if /// the file is local (not on a network mount). @@ -594,7 +594,7 @@ public: /// /// @return /// A shared pointer to the memory mapped data. This shared - /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer can contain a nullptr DataBuffer pointer, so the contained /// pointer must be checked prior to using it. //------------------------------------------------------------------ lldb::DataBufferSP @@ -624,16 +624,15 @@ public: /// /// @return /// A shared pointer to the memory mapped data. This shared - /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer can contain a nullptr DataBuffer pointer, so the contained /// pointer must be checked prior to using it. //------------------------------------------------------------------ lldb::DataBufferSP - ReadFileContents (off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = NULL) const; + ReadFileContents(off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = nullptr) const; size_t ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const; - //------------------------------------------------------------------ /// Read the entire contents of a file as data that can be used /// as a C string. @@ -643,11 +642,11 @@ public: /// /// @return /// A shared pointer to the data. This shared pointer can - /// contain a NULL DataBuffer pointer, so the contained pointer + /// contain a nullptr DataBuffer pointer, so the contained pointer /// must be checked prior to using it. //------------------------------------------------------------------ lldb::DataBufferSP - ReadFileContentsAsCString(Error *error_ptr = NULL); + ReadFileContentsAsCString(Error *error_ptr = nullptr); //------------------------------------------------------------------ /// Normalize a pathname by collapsing redundant separators and @@ -719,6 +718,7 @@ public: { m_is_resolved = is_resolved; } + //------------------------------------------------------------------ /// Read the file into an array of strings, one per line. /// @@ -835,5 +835,4 @@ Stream& operator << (Stream& s, const FileSpec& f); } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // liblldb_FileSpec_h_ +#endif // liblldb_FileSpec_h_ diff --git a/include/lldb/Host/FileSystem.h b/include/lldb/Host/FileSystem.h index bea1ec80172e..465ad451bdd6 100644 --- a/include/lldb/Host/FileSystem.h +++ b/include/lldb/Host/FileSystem.h @@ -22,6 +22,8 @@ namespace lldb_private class FileSystem { public: + static const char *DEV_NULL; + static FileSpec::PathSyntax GetNativePathSyntax(); static Error MakeDirectory(const FileSpec &file_spec, uint32_t mode); @@ -35,9 +37,12 @@ class FileSystem static bool GetFileExists(const FileSpec &file_spec); static Error Hardlink(const FileSpec &src, const FileSpec &dst); + static int GetHardlinkCount(const FileSpec &file_spec); static Error Symlink(const FileSpec &src, const FileSpec &dst); static Error Readlink(const FileSpec &src, FileSpec &dst); static Error Unlink(const FileSpec &file_spec); + + static Error ResolveSymbolicLink(const FileSpec &src, FileSpec &dst); static bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high); static bool CalculateMD5(const FileSpec &file_spec, diff --git a/include/lldb/Host/HostGetOpt.h b/include/lldb/Host/HostGetOpt.h index 761c1a118600..6f512915d33c 100644 --- a/include/lldb/Host/HostGetOpt.h +++ b/include/lldb/Host/HostGetOpt.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #pragma once -#ifndef _MSC_VER +#if !defined(_MSC_VER) && !defined(__NetBSD__) #ifdef _WIN32 #define _BSD_SOURCE // Required so that getopt.h defines optreset @@ -19,6 +19,6 @@ #else -#include +#include #endif diff --git a/include/lldb/Host/HostInfo.h b/include/lldb/Host/HostInfo.h index 6bb009997896..96094389c703 100644 --- a/include/lldb/Host/HostInfo.h +++ b/include/lldb/Host/HostInfo.h @@ -48,6 +48,9 @@ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "lldb/Host/freebsd/HostInfoFreeBSD.h" #define HOST_INFO_TYPE HostInfoFreeBSD +#elif defined(__NetBSD__) +#include "lldb/Host/netbsd/HostInfoNetBSD.h" +#define HOST_INFO_TYPE HostInfoNetBSD #elif defined(__APPLE__) #include "lldb/Host/macosx/HostInfoMacOSX.h" #define HOST_INFO_TYPE HostInfoMacOSX diff --git a/include/lldb/Host/HostNativeThread.h b/include/lldb/Host/HostNativeThread.h index f39c775df8e3..b0411cad7a3e 100644 --- a/include/lldb/Host/HostNativeThread.h +++ b/include/lldb/Host/HostNativeThread.h @@ -18,6 +18,8 @@ #include "lldb/Host/linux/HostThreadLinux.h" #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "lldb/Host/freebsd/HostThreadFreeBSD.h" +#elif defined(__NetBSD__) +#include "lldb/Host/netbsd/HostThreadNetBSD.h" #elif defined(__APPLE__) #include "lldb/Host/macosx/HostThreadMacOSX.h" #endif diff --git a/include/lldb/Host/HostNativeThreadForward.h b/include/lldb/Host/HostNativeThreadForward.h index e6bd426673b3..520031af6488 100644 --- a/include/lldb/Host/HostNativeThreadForward.h +++ b/include/lldb/Host/HostNativeThreadForward.h @@ -21,6 +21,9 @@ typedef HostThreadLinux HostNativeThread; #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) class HostThreadFreeBSD; typedef HostThreadFreeBSD HostNativeThread; +#elif defined(__NetBSD__) +class HostThreadNetBSD; +typedef HostThreadNetBSD HostNativeThread; #elif defined(__APPLE__) class HostThreadMacOSX; typedef HostThreadMacOSX HostNativeThread; diff --git a/include/lldb/Host/MainLoopBase.h b/include/lldb/Host/MainLoopBase.h index bff2ce78110d..da14349cf82e 100644 --- a/include/lldb/Host/MainLoopBase.h +++ b/include/lldb/Host/MainLoopBase.h @@ -60,25 +60,25 @@ public: protected: ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) - { return ReadHandleUP(new ReadHandle(*this, object_sp)); } + { return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle())); } virtual void - UnregisterReadObject(const lldb::IOObjectSP &object_sp) + UnregisterReadObject(IOObject::WaitableHandle handle) { llvm_unreachable("Not implemented"); } private: class ReadHandle { public: - ~ReadHandle() { m_mainloop.UnregisterReadObject(m_object_sp); } + ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); } private: - ReadHandle(MainLoopBase &mainloop, const lldb::IOObjectSP &object_sp) - : m_mainloop(mainloop), m_object_sp(object_sp) + ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle) + : m_mainloop(mainloop), m_handle(handle) { } MainLoopBase &m_mainloop; - lldb::IOObjectSP m_object_sp; + IOObject::WaitableHandle m_handle; friend class MainLoopBase; DISALLOW_COPY_AND_ASSIGN(ReadHandle); diff --git a/include/lldb/Host/MonitoringProcessLauncher.h b/include/lldb/Host/MonitoringProcessLauncher.h index 3c3e66108f8a..f5d0a92aa8de 100644 --- a/include/lldb/Host/MonitoringProcessLauncher.h +++ b/include/lldb/Host/MonitoringProcessLauncher.h @@ -10,6 +10,10 @@ #ifndef lldb_Host_MonitoringProcessLauncher_h_ #define lldb_Host_MonitoringProcessLauncher_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Host/ProcessLauncher.h" namespace lldb_private @@ -20,11 +24,12 @@ class MonitoringProcessLauncher : public ProcessLauncher public: explicit MonitoringProcessLauncher(std::unique_ptr delegate_launcher); - virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error); + HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error) override; private: std::unique_ptr m_delegate_launcher; }; -} -#endif +} // namespace lldb_private + +#endif // lldb_Host_MonitoringProcessLauncher_h_ diff --git a/include/lldb/Host/Mutex.h b/include/lldb/Host/Mutex.h index 496dd0496c13..5a529fb4554d 100644 --- a/include/lldb/Host/Mutex.h +++ b/include/lldb/Host/Mutex.h @@ -9,15 +9,17 @@ #ifndef liblldb_Mutex_h_ #define liblldb_Mutex_h_ -#if defined(__cplusplus) - -#include "lldb/lldb-types.h" -#include +// C Includes +// C++ Includes #ifdef LLDB_CONFIGURATION_DEBUG #include #endif +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-types.h" + namespace lldb_private { //---------------------------------------------------------------------- @@ -85,7 +87,7 @@ public: Locker(Mutex* m); //-------------------------------------------------------------- - /// Desstructor + /// Destructor /// /// Unlocks any valid pthread_mutex_t that this object may /// contain. @@ -97,7 +99,7 @@ public: /// /// Unlock the current mutex in this object (if it contains a /// valid mutex) and lock the new \a mutex object if it is - /// non-NULL. + /// non-nullptr. //-------------------------------------------------------------- void Lock (Mutex &mutex); @@ -120,15 +122,15 @@ public: /// will not take ownership of the mutex. /// /// @return - /// Returns \b true if the lock was aquired and the this + /// Returns \b true if the lock was acquired and the this /// object will unlock the mutex when it goes out of scope, /// returns \b false otherwise. //-------------------------------------------------------------- bool - TryLock (Mutex &mutex, const char *failure_message = NULL); + TryLock(Mutex &mutex, const char *failure_message = nullptr); bool - TryLock (Mutex *mutex, const char *failure_message = NULL) + TryLock(Mutex *mutex, const char *failure_message = nullptr) { if (mutex) return TryLock(*mutex, failure_message); @@ -150,7 +152,6 @@ public: const Locker& operator=(const Locker&); }; - //------------------------------------------------------------------ /// Default constructor. /// @@ -213,7 +214,7 @@ public: virtual #endif int - TryLock(const char *failure_message = NULL); + TryLock(const char *failure_message = nullptr); //------------------------------------------------------------------ /// Unlock the mutex. @@ -262,16 +263,16 @@ public: TrackingMutex(Mutex::Type type) : Mutex (type) {} virtual - ~TrackingMutex() {} + ~TrackingMutex() = default; virtual int Unlock (); virtual int - TryLock (const char *failure_message = NULL) + TryLock(const char *failure_message = nullptr) { int return_value = Mutex::TryLock(); - if (return_value != 0 && failure_message != NULL) + if (return_value != 0 && failure_message != nullptr) { m_failure_message.assign(failure_message); m_thread_that_tried = pthread_self(); @@ -291,7 +292,7 @@ public: LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {} virtual - ~LoggingMutex() {} + ~LoggingMutex() = default; virtual int Lock (); @@ -300,13 +301,13 @@ public: Unlock (); virtual int - TryLock (const char *failure_message = NULL); + TryLock(const char *failure_message = nullptr); + protected: bool m_locked; }; -#endif +#endif // LLDB_CONFIGURATION_DEBUG } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif +#endif // liblldb_Mutex_h_ diff --git a/include/lldb/Host/OptionParser.h b/include/lldb/Host/OptionParser.h index 5aa7db5d34bf..175a1973c7af 100644 --- a/include/lldb/Host/OptionParser.h +++ b/include/lldb/Host/OptionParser.h @@ -11,6 +11,7 @@ #define liblldb_OptionParser_h_ #include +#include "lldb/Host/Mutex.h" struct option; @@ -38,7 +39,7 @@ public: eOptionalArgument }; - static void Prepare(); + static void Prepare(Mutex::Locker &locker); static void EnableError(bool error); diff --git a/include/lldb/Host/Predicate.h b/include/lldb/Host/Predicate.h index ae6c99155fe0..4f386dc1dd0b 100644 --- a/include/lldb/Host/Predicate.h +++ b/include/lldb/Host/Predicate.h @@ -9,13 +9,17 @@ #ifndef liblldb_Predicate_h_ #define liblldb_Predicate_h_ -#if defined(__cplusplus) +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-defines.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Condition.h" -#include -#include //#define DB_PTHREAD_LOG_EVENTS @@ -29,7 +33,6 @@ 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. - } PredicateBroadcastType; //---------------------------------------------------------------------- @@ -46,7 +49,6 @@ template class Predicate { public: - //------------------------------------------------------------------ /// Default constructor. /// @@ -81,10 +83,7 @@ public: /// /// Destroy the condition, mutex, and T objects. //------------------------------------------------------------------ - ~Predicate () - { - } - + ~Predicate() = default; //------------------------------------------------------------------ /// Value get accessor. @@ -205,7 +204,7 @@ public: /// The bits we are waiting to be set in \a m_value. /// /// @param[in] abstime - /// If non-NULL, the absolute time at which we should stop + /// If non-nullptr, the absolute time at which we should stop /// waiting, else wait an infinite amount of time. /// /// @return @@ -214,7 +213,7 @@ public: /// occurred. //------------------------------------------------------------------ T - WaitForSetValueBits (T bits, const TimeValue *abstime = NULL) + WaitForSetValueBits(T bits, const TimeValue *abstime = nullptr) { int err = 0; // pthread_cond_timedwait() or pthread_cond_wait() will atomically @@ -255,7 +254,7 @@ public: /// The bits we are waiting to be reset in \a m_value. /// /// @param[in] abstime - /// If non-NULL, the absolute time at which we should stop + /// If non-nullptr, the absolute time at which we should stop /// waiting, else wait an infinite amount of time. /// /// @return @@ -263,7 +262,7 @@ public: /// unrecoverable error occurs. //------------------------------------------------------------------ T - WaitForResetValueBits (T bits, const TimeValue *abstime = NULL) + WaitForResetValueBits(T bits, const TimeValue *abstime = nullptr) { int err = 0; @@ -306,7 +305,7 @@ public: /// The value we want \a m_value to be equal to. /// /// @param[in] abstime - /// If non-NULL, the absolute time at which we should stop + /// If non-nullptr, the absolute time at which we should stop /// waiting, else wait an infinite amount of time. /// /// @param[out] timed_out @@ -318,7 +317,7 @@ public: /// @li \b false otherwise //------------------------------------------------------------------ bool - WaitForValueEqualTo (T value, const TimeValue *abstime = NULL, bool *timed_out = NULL) + WaitForValueEqualTo(T value, const TimeValue *abstime = nullptr, bool *timed_out = nullptr) { int err = 0; // pthread_cond_timedwait() or pthread_cond_wait() will atomically @@ -366,7 +365,7 @@ public: /// returned. /// /// @param[in] abstime - /// If non-NULL, the absolute time at which we should stop + /// If non-nullptr, the absolute time at which we should stop /// waiting, else wait an infinite amount of time. /// /// @param[out] timed_out @@ -378,7 +377,9 @@ public: /// @li \b false otherwise //------------------------------------------------------------------ bool - WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL) + WaitForValueEqualToAndSetValueTo(T wait_value, T new_value, + const TimeValue *abstime = nullptr, + bool *timed_out = nullptr) { int err = 0; // pthread_cond_timedwait() or pthread_cond_wait() will atomically @@ -408,7 +409,6 @@ public: return false; } - //------------------------------------------------------------------ /// Wait for \a m_value to not be equal to \a value. /// @@ -430,7 +430,7 @@ public: /// The new value if \b true is returned. /// /// @param[in] abstime - /// If non-NULL, the absolute time at which we should stop + /// If non-nullptr, the absolute time at which we should stop /// waiting, else wait an infinite amount of time. /// /// @return @@ -438,7 +438,7 @@ public: /// @li \b false otherwise //------------------------------------------------------------------ bool - WaitForValueNotEqualTo (T value, T &new_value, const TimeValue *abstime = NULL) + WaitForValueNotEqualTo(T value, T &new_value, const TimeValue *abstime = nullptr) { int err = 0; // pthread_cond_timedwait() or pthread_cond_wait() will atomically @@ -473,7 +473,6 @@ protected: Condition m_condition; ///< The pthread condition variable to use for signaling that data available or changed. private: - //------------------------------------------------------------------ /// Broadcast if needed. /// @@ -500,11 +499,9 @@ private: m_condition.Broadcast(); } - DISALLOW_COPY_AND_ASSIGN(Predicate); }; } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // #ifndef liblldb_Predicate_h_ +#endif // liblldb_Predicate_h_ diff --git a/include/lldb/Host/ProcessRunLock.h b/include/lldb/Host/ProcessRunLock.h index eca1ad375fc6..ceb1e90be757 100644 --- a/include/lldb/Host/ProcessRunLock.h +++ b/include/lldb/Host/ProcessRunLock.h @@ -9,13 +9,17 @@ #ifndef liblldb_ProcessRunLock_h_ #define liblldb_ProcessRunLock_h_ -#if defined(__cplusplus) +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-defines.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Condition.h" -#include -#include //---------------------------------------------------------------------- /// Enumerations for broadcasting. @@ -34,17 +38,18 @@ class ProcessRunLock public: ProcessRunLock(); ~ProcessRunLock(); + bool ReadTryLock (); bool ReadUnlock (); bool SetRunning (); bool TrySetRunning (); bool SetStopped (); -public: + class ProcessRunLocker { public: ProcessRunLocker () : - m_lock (NULL) + m_lock (nullptr) { } @@ -82,11 +87,12 @@ public: if (m_lock) { m_lock->ReadUnlock(); - m_lock = NULL; + m_lock = nullptr; } } ProcessRunLock *m_lock; + private: DISALLOW_COPY_AND_ASSIGN(ProcessRunLocker); }; @@ -94,11 +100,11 @@ public: protected: lldb::rwlock_t m_rwlock; bool m_running; + private: DISALLOW_COPY_AND_ASSIGN(ProcessRunLock); }; } // namespace lldb_private -#endif // #if defined(__cplusplus) -#endif // #ifndef liblldb_ProcessRunLock_h_ +#endif // liblldb_ProcessRunLock_h_ diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h index f4599b5ab87b..a38b42f817c6 100644 --- a/include/lldb/Host/Socket.h +++ b/include/lldb/Host/Socket.h @@ -10,6 +10,7 @@ #ifndef liblldb_Host_Socket_h_ #define liblldb_Host_Socket_h_ +#include #include #include "lldb/lldb-private.h" @@ -45,13 +46,19 @@ public: { ProtocolTcp, ProtocolUdp, - ProtocolUnixDomain + ProtocolUnixDomain, + ProtocolUnixAbstract } SocketProtocol; static const NativeSocket kInvalidSocketValue; - Socket(NativeSocket socket, SocketProtocol protocol, bool should_close); - ~Socket(); + ~Socket() override; + + static std::unique_ptr Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error); + + virtual Error Connect(llvm::StringRef name) = 0; + virtual Error Listen(llvm::StringRef name, int backlog) = 0; + virtual Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) = 0; // Initialize a Tcp Socket object in listening mode. listen and accept are implemented // separately because the caller may wish to manipulate or query the socket after it is @@ -66,43 +73,23 @@ public: static Error UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); static Error UnixDomainConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); static Error UnixDomainAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); - - // Blocks on a listening socket until a connection is received. This method assumes that - // |this->m_socket| is a listening socket, created via either TcpListen() or via the native - // constructor that takes a NativeSocket, which itself was created via a call to |listen()| - Error BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixAbstractConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); + static Error UnixAbstractAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket); int GetOption (int level, int option_name, int &option_value); int SetOption (int level, int option_name, int option_value); - // returns port number or 0 if error - static uint16_t GetLocalPortNumber (const NativeSocket& socket); - - // returns port number or 0 if error - uint16_t GetLocalPortNumber () const; - - // returns ip address string or empty string if error - std::string GetLocalIPAddress () const; - - // must be connected - // returns port number or 0 if error - uint16_t GetRemotePortNumber () const; - - // must be connected - // returns ip address string or empty string if error - std::string GetRemoteIPAddress () const; - NativeSocket GetNativeSocket () const { return m_socket; } SocketProtocol GetSocketProtocol () const { return m_protocol; } - virtual Error Read (void *buf, size_t &num_bytes); - virtual Error Write (const void *buf, size_t &num_bytes); + Error Read (void *buf, size_t &num_bytes) override; + Error Write (const void *buf, size_t &num_bytes) override; virtual Error PreDisconnect (); - virtual Error Close (); + Error Close() override; - virtual bool IsValid () const { return m_socket != kInvalidSocketValue; } - virtual WaitableHandle GetWaitableHandle (); + bool IsValid () const override { return m_socket != kInvalidSocketValue; } + WaitableHandle GetWaitableHandle () override; static bool DecodeHostAndPort (llvm::StringRef host_and_port, @@ -112,10 +99,20 @@ public: Error *error_ptr); protected: + Socket(NativeSocket socket, SocketProtocol protocol, bool should_close); + + virtual size_t Send(const void *buf, const size_t num_bytes); + + static void SetLastError(Error &error); + static NativeSocket CreateSocket( + const int domain, const int type, const int protocol, bool child_processes_inherit, Error& error); + static NativeSocket AcceptSocket( + NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit, Error& error); + SocketProtocol m_protocol; NativeSocket m_socket; - SocketAddress m_udp_send_sockaddr; // Send address used for UDP connections. }; -} -#endif +} // namespace lldb_private + +#endif // liblldb_Host_Socket_h_ diff --git a/include/lldb/Host/Symbols.h b/include/lldb/Host/Symbols.h index d6c86333d709..0ca864c8c85c 100644 --- a/include/lldb/Host/Symbols.h +++ b/include/lldb/Host/Symbols.h @@ -29,7 +29,7 @@ public: // Locating the file should happen only on the local computer or using // the current computers global settings. //---------------------------------------------------------------------- - static FileSpec + static ModuleSpec LocateExecutableObjectFile (const ModuleSpec &module_spec); //---------------------------------------------------------------------- diff --git a/include/lldb/Host/XML.h b/include/lldb/Host/XML.h index e3547d834635..3ebd2c6f79ec 100644 --- a/include/lldb/Host/XML.h +++ b/include/lldb/Host/XML.h @@ -11,25 +11,23 @@ #define liblldb_XML_h_ // C Includes - #if defined( LIBXML2_DEFINED ) #include #endif // C++ Includes - #include #include #include // Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + // Project includes #include "lldb/lldb-private.h" -#include "llvm/ADT/StringRef.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/StructuredData.h" - namespace lldb_private { #if defined( LIBXML2_DEFINED ) @@ -94,7 +92,7 @@ namespace lldb_private { GetChild () const; llvm::StringRef - GetAttributeValue(const char *name, const char *fail_value = NULL) const; + GetAttributeValue(const char *name, const char *fail_value = nullptr) const; XMLNode FindFirstChildElementWithName (const char *name) const; @@ -140,7 +138,6 @@ namespace lldb_private { class XMLDocument { public: - XMLDocument (); ~XMLDocument (); @@ -163,7 +160,7 @@ namespace lldb_private { ParseMemory (const char *xml, size_t xml_length, const char *url = "untitled.xml"); //---------------------------------------------------------------------- - // If \a name is NULL, just get the root element node, else only return + // If \a name is nullptr, just get the root element node, else only return // a value XMLNode if the name of the root element matches \a name. //---------------------------------------------------------------------- XMLNode @@ -216,7 +213,6 @@ namespace lldb_private { GetStructuredData(); protected: - // Using a node returned from GetValueNode() extract its value as a // string (if possible). Array and dictionary nodes will return false // as they have no string value. Boolean nodes will return true and @@ -229,6 +225,7 @@ namespace lldb_private { XMLDocument m_xml_doc; XMLNode m_dict_node; }; + } // namespace lldb_private #endif // liblldb_XML_h_ diff --git a/include/lldb/Host/common/GetOptInc.h b/include/lldb/Host/common/GetOptInc.h new file mode 100644 index 000000000000..f79644017ca5 --- /dev/null +++ b/include/lldb/Host/common/GetOptInc.h @@ -0,0 +1,65 @@ +#pragma once + +#include "lldb/lldb-defines.h" + +#if defined(_MSC_VER) +#define REPLACE_GETOPT +#define REPLACE_GETOPT_LONG +#endif +#if defined(_MSC_VER) || defined(__NetBSD__) +#define REPLACE_GETOPT_LONG_ONLY +#endif + +#if defined(REPLACE_GETOPT) +// from getopt.h +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +// option structure +struct option +{ + const char *name; + // has_arg can't be an enum because some compilers complain about + // type mismatches in all the code that assumes it is an int. + int has_arg; + int *flag; + int val; +}; + +int getopt( int argc, char * const argv[], const char *optstring ); + +// from getopt.h +extern char * optarg; +extern int optind; +extern int opterr; +extern int optopt; + +// defined in unistd.h +extern int optreset; +#else +# include +# include +#endif + +#if defined(REPLACE_GETOPT_LONG) +int getopt_long +( + int argc, + char * const *argv, + const char *optstring, + const struct option *longopts, + int *longindex +); +#endif + +#if defined(REPLACE_GETOPT_LONG_ONLY) +int getopt_long_only +( + int argc, + char * const *argv, + const char *optstring, + const struct option *longopts, + int *longindex +); +#endif diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h index 4f0f3a962d32..7236bf659042 100644 --- a/include/lldb/Host/common/NativeProcessProtocol.h +++ b/include/lldb/Host/common/NativeProcessProtocol.h @@ -16,6 +16,7 @@ #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" #include "lldb/Host/Mutex.h" +#include "lldb/Host/MainLoop.h" #include "llvm/ADT/StringRef.h" #include "NativeBreakpointList.h" @@ -284,10 +285,6 @@ namespace lldb_private bool UnregisterNativeDelegate (NativeDelegate &native_delegate); - // Called before termination of NativeProcessProtocol's instance. - virtual void - Terminate (); - virtual Error GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) = 0; @@ -307,6 +304,11 @@ namespace lldb_private /// inferior. Must outlive the NativeProcessProtocol /// instance. /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// /// @param[out] process_sp /// On successful return from the method, this parameter /// contains the shared pointer to the @@ -320,6 +322,7 @@ namespace lldb_private static Error Launch (ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp); //------------------------------------------------------------------ @@ -335,6 +338,11 @@ namespace lldb_private /// inferior. Must outlive the NativeProcessProtocol /// instance. /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// /// @param[out] process_sp /// On successful return from the method, this parameter /// contains the shared pointer to the @@ -348,6 +356,7 @@ namespace lldb_private static Error Attach (lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp); protected: diff --git a/include/lldb/Host/common/TCPSocket.h b/include/lldb/Host/common/TCPSocket.h new file mode 100644 index 000000000000..0ffe9c87bfa4 --- /dev/null +++ b/include/lldb/Host/common/TCPSocket.h @@ -0,0 +1,46 @@ +//===-- TCPSocket.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_TCPSocket_h_ +#define liblldb_TCPSocket_h_ + +#include "lldb/Host/Socket.h" + +namespace lldb_private +{ + class TCPSocket: public Socket + { + public: + TCPSocket(NativeSocket socket, bool should_close); + TCPSocket(bool child_processes_inherit, Error &error); + + // returns port number or 0 if error + uint16_t GetLocalPortNumber () const; + + // returns ip address string or empty string if error + std::string GetLocalIPAddress () const; + + // must be connected + // returns port number or 0 if error + uint16_t GetRemotePortNumber () const; + + // must be connected + // returns ip address string or empty string if error + std::string GetRemoteIPAddress () const; + + int SetOptionNoDelay(); + int SetOptionReuseAddress(); + + Error Connect(llvm::StringRef name) override; + Error Listen(llvm::StringRef name, int backlog) override; + Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) override; + }; +} + +#endif // ifndef liblldb_TCPSocket_h_ diff --git a/include/lldb/Host/common/UDPSocket.h b/include/lldb/Host/common/UDPSocket.h new file mode 100644 index 000000000000..afc1ec719626 --- /dev/null +++ b/include/lldb/Host/common/UDPSocket.h @@ -0,0 +1,35 @@ +//===-- UDPSocket.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_UDPSocket_h_ +#define liblldb_UDPSocket_h_ + +#include "lldb/Host/Socket.h" + +namespace lldb_private +{ + class UDPSocket: public Socket + { + public: + UDPSocket(bool child_processes_inherit, Error &error); + + static Error Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket); + private: + UDPSocket(NativeSocket socket); + + size_t Send(const void *buf, const size_t num_bytes) override; + Error Connect(llvm::StringRef name) override; + Error Listen(llvm::StringRef name, int backlog) override; + Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override; + + SocketAddress m_send_sockaddr; + }; +} + +#endif // ifndef liblldb_UDPSocket_h_ diff --git a/include/lldb/Host/netbsd/Config.h b/include/lldb/Host/netbsd/Config.h new file mode 100644 index 000000000000..1e9f55299d52 --- /dev/null +++ b/include/lldb/Host/netbsd/Config.h @@ -0,0 +1,28 @@ +//===-- Config.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//---------------------------------------------------------------------- +// LLDB currently doesn't have a dynamic configuration mechanism, so we +// are going to hardcode things for now. Eventually these files will +// be auto generated by some configuration script that can detect +// platform functionality availability. +//---------------------------------------------------------------------- + +#ifndef liblldb_Platform_Config_h_ +#define liblldb_Platform_Config_h_ + +#define LLDB_CONFIG_TERMIOS_SUPPORTED 1 + +#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 + +//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 + +//#define LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 1 + +#endif // #ifndef liblldb_Platform_Config_h_ diff --git a/include/lldb/Host/netbsd/HostInfoNetBSD.h b/include/lldb/Host/netbsd/HostInfoNetBSD.h new file mode 100644 index 000000000000..34a29346c2ef --- /dev/null +++ b/include/lldb/Host/netbsd/HostInfoNetBSD.h @@ -0,0 +1,30 @@ +//===-- HostInfoNetBSD.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_netbsd_HostInfoNetBSD_h_ +#define lldb_Host_netbsd_HostInfoNetBSD_h_ + +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/posix/HostInfoPosix.h" + +namespace lldb_private +{ + +class HostInfoNetBSD : public HostInfoPosix +{ + public: + static uint32_t GetMaxThreadNameLength(); + static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); + static bool GetOSBuildString(std::string &s); + static bool GetOSKernelDescription(std::string &s); + static FileSpec GetProgramFileSpec(); +}; +} + +#endif diff --git a/include/lldb/Host/netbsd/HostThreadNetBSD.h b/include/lldb/Host/netbsd/HostThreadNetBSD.h new file mode 100644 index 000000000000..2ce1e48fa045 --- /dev/null +++ b/include/lldb/Host/netbsd/HostThreadNetBSD.h @@ -0,0 +1,32 @@ +//===-- HostThreadNetBSD.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_netbsd_HostThreadNetBSD_h_ +#define lldb_Host_netbsd_HostThreadNetBSD_h_ + +#include "lldb/Host/posix/HostThreadPosix.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" + +namespace lldb_private +{ + +class HostThreadNetBSD : public HostThreadPosix +{ + public: + HostThreadNetBSD(); + HostThreadNetBSD(lldb::thread_t thread); + + static void SetName(lldb::thread_t tid, llvm::StringRef &name); + static void GetName(lldb::thread_t tid, llvm::SmallVectorImpl &name); +}; +} + +#endif diff --git a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h index 2e0fd705b2a8..7e7904cd5fa8 100644 --- a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -34,13 +34,24 @@ class SocketAddress; class ConnectionFileDescriptor : public Connection { public: + static const char* LISTEN_SCHEME; + static const char* ACCEPT_SCHEME; + static const char* UNIX_ACCEPT_SCHEME; + static const char* CONNECT_SCHEME; + static const char* TCP_CONNECT_SCHEME; + static const char* UDP_SCHEME; + static const char* UNIX_CONNECT_SCHEME; + static const char* UNIX_ABSTRACT_CONNECT_SCHEME; + static const char* FD_SCHEME; + static const char* FILE_SCHEME; + ConnectionFileDescriptor(bool child_processes_inherit = false); ConnectionFileDescriptor(int fd, bool owns_fd); ConnectionFileDescriptor(Socket* socket); - virtual ~ConnectionFileDescriptor(); + ~ConnectionFileDescriptor() override; bool IsConnected() const override; @@ -84,6 +95,8 @@ class ConnectionFileDescriptor : public Connection lldb::ConnectionStatus NamedSocketAccept(const char *socket_name, Error *error_ptr); + lldb::ConnectionStatus UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr); + lldb::IOObjectSP m_read_sp; lldb::IOObjectSP m_write_sp; diff --git a/include/lldb/Host/posix/DomainSocket.h b/include/lldb/Host/posix/DomainSocket.h new file mode 100644 index 000000000000..76f58e4f03b2 --- /dev/null +++ b/include/lldb/Host/posix/DomainSocket.h @@ -0,0 +1,37 @@ +//===-- DomainSocket.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_DomainSocket_h_ +#define liblldb_DomainSocket_h_ + +#include "lldb/Host/Socket.h" + +namespace lldb_private +{ + class DomainSocket: public Socket + { + public: + DomainSocket(bool child_processes_inherit, Error &error); + + Error Connect(llvm::StringRef name) override; + Error Listen(llvm::StringRef name, int backlog) override; + Error Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) override; + + protected: + DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error); + + virtual size_t GetNameOffset() const; + virtual void DeleteSocketFile(llvm::StringRef name); + + private: + DomainSocket(NativeSocket socket); + }; +} + +#endif // ifndef liblldb_DomainSocket_h_ diff --git a/include/lldb/Host/posix/HostProcessPosix.h b/include/lldb/Host/posix/HostProcessPosix.h index c9534991361b..5db49d17d757 100644 --- a/include/lldb/Host/posix/HostProcessPosix.h +++ b/include/lldb/Host/posix/HostProcessPosix.h @@ -10,6 +10,10 @@ #ifndef lldb_Host_HostProcesPosix_h_ #define lldb_Host_HostProcesPosix_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" #include "lldb/Host/HostNativeProcessBase.h" @@ -24,7 +28,7 @@ class HostProcessPosix : public HostNativeProcessBase public: HostProcessPosix(); HostProcessPosix(lldb::process_t process); - virtual ~HostProcessPosix(); + ~HostProcessPosix() override; virtual Error Signal(int signo) const; static Error Signal(lldb::process_t process, int signo); @@ -37,6 +41,7 @@ class HostProcessPosix : public HostNativeProcessBase HostThread StartMonitoring(HostProcess::MonitorCallback callback, void *callback_baton, bool monitor_signals) override; }; -} -#endif +} // namespace lldb_private + +#endif // lldb_Host_HostProcesPosix_h_ diff --git a/include/lldb/Host/posix/HostThreadPosix.h b/include/lldb/Host/posix/HostThreadPosix.h index 8839b8d4068b..e044313cd7dc 100644 --- a/include/lldb/Host/posix/HostThreadPosix.h +++ b/include/lldb/Host/posix/HostThreadPosix.h @@ -22,13 +22,14 @@ class HostThreadPosix : public HostNativeThreadBase public: HostThreadPosix(); HostThreadPosix(lldb::thread_t thread); - virtual ~HostThreadPosix(); + ~HostThreadPosix() override; Error Join(lldb::thread_result_t *result) override; Error Cancel() override; Error Detach(); }; -} -#endif +} // namespace lldb_private + +#endif // lldb_Host_posix_HostThreadPosix_h_ diff --git a/include/lldb/Host/posix/LockFilePosix.h b/include/lldb/Host/posix/LockFilePosix.h index 999397ec2bb5..628571c8dacd 100644 --- a/include/lldb/Host/posix/LockFilePosix.h +++ b/include/lldb/Host/posix/LockFilePosix.h @@ -18,7 +18,7 @@ class LockFilePosix : public LockFileBase { public: explicit LockFilePosix (int fd); - ~LockFilePosix (); + ~LockFilePosix () override; protected: Error @@ -37,6 +37,6 @@ protected: DoUnlock () override; }; -} // namespace lldb_private +} // namespace lldb_private -#endif // liblldb_Host_posix_LockFilePosix_h_ +#endif // liblldb_Host_posix_LockFilePosix_h_ diff --git a/include/lldb/Host/posix/MainLoopPosix.h b/include/lldb/Host/posix/MainLoopPosix.h index 9a665ded295e..225cebde4bce 100644 --- a/include/lldb/Host/posix/MainLoopPosix.h +++ b/include/lldb/Host/posix/MainLoopPosix.h @@ -60,7 +60,7 @@ public: protected: void - UnregisterReadObject(const lldb::IOObjectSP &object_sp) override; + UnregisterReadObject(IOObject::WaitableHandle handle) override; void UnregisterSignal(int signo); diff --git a/include/lldb/Initialization/SystemInitializerCommon.h b/include/lldb/Initialization/SystemInitializerCommon.h index af66c93a5e48..b46bf506998b 100644 --- a/include/lldb/Initialization/SystemInitializerCommon.h +++ b/include/lldb/Initialization/SystemInitializerCommon.h @@ -28,11 +28,12 @@ class SystemInitializerCommon : public SystemInitializer { public: SystemInitializerCommon(); - virtual ~SystemInitializerCommon(); + ~SystemInitializerCommon() override; void Initialize() override; void Terminate() override; }; -} -#endif +} // namespace lldb_private + +#endif // LLDB_INITIALIZATION_SYSTEM_INITIALIZER_COMMON_H diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h index e11636b63f17..e79318ba5626 100644 --- a/include/lldb/Interpreter/Args.h +++ b/include/lldb/Interpreter/Args.h @@ -424,6 +424,9 @@ public: static void ExpandEscapedCharacters (const char *src, std::string &dst); + static std::string + EscapeLLDBCommandArgument (const std::string& arg, char quote_char); + // This one isn't really relevant to Arguments per se, but we're using the Args as a // general strings container, so... void diff --git a/include/lldb/Interpreter/CommandCompletions.h b/include/lldb/Interpreter/CommandCompletions.h index 9df3041584ea..27ab45b3fa1f 100644 --- a/include/lldb/Interpreter/CommandCompletions.h +++ b/include/lldb/Interpreter/CommandCompletions.h @@ -54,7 +54,6 @@ public: // so you can add custom enums starting from here in your Option class. // Also if you & in this bit the base code will not process the option. eCustomCompletion = (1u << 9) - } CommonCompletionTypes; struct CommonCompletionElement @@ -83,6 +82,7 @@ public: SearchFilter *searcher, bool &word_complete, StringList &matches); + static int DiskDirectories (CommandInterpreter &interpreter, const char *partial_file_name, @@ -170,16 +170,16 @@ public: int max_return_elements, StringList &matches); - virtual ~Completer (); + ~Completer() override; - virtual CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete) = 0; + CallbackReturn + SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) override = 0; - virtual Depth - GetDepth () = 0; + Depth + GetDepth() override = 0; virtual size_t DoCompletion (SearchFilter *filter) = 0; @@ -190,8 +190,9 @@ public: int m_match_start_point; int m_max_return_elements; StringList &m_matches; + private: - DISALLOW_COPY_AND_ASSIGN (Completer); + DISALLOW_COPY_AND_ASSIGN(Completer); }; //---------------------------------------------------------------------- @@ -200,7 +201,6 @@ public: class SourceFileCompleter : public Completer { public: - SourceFileCompleter (CommandInterpreter &interpreter, bool include_support_files, const char *completion_str, @@ -208,24 +208,24 @@ public: int max_return_elements, StringList &matches); - virtual Searcher::Depth GetDepth (); + Searcher::Depth GetDepth() override; - virtual Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete); + Searcher::CallbackReturn + SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) override; size_t - DoCompletion (SearchFilter *filter); + DoCompletion(SearchFilter *filter) override; private: bool m_include_support_files; FileSpecList m_matching_files; const char *m_file_name; const char *m_dir_name; - DISALLOW_COPY_AND_ASSIGN (SourceFileCompleter); + DISALLOW_COPY_AND_ASSIGN(SourceFileCompleter); }; //---------------------------------------------------------------------- @@ -234,29 +234,28 @@ public: class ModuleCompleter : public Completer { public: - ModuleCompleter (CommandInterpreter &interpreter, const char *completion_str, int match_start_point, int max_return_elements, StringList &matches); - virtual Searcher::Depth GetDepth (); + Searcher::Depth GetDepth() override; - virtual Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete); + Searcher::CallbackReturn + SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) override; size_t - DoCompletion (SearchFilter *filter); + DoCompletion(SearchFilter *filter) override; private: const char *m_file_name; const char *m_dir_name; - DISALLOW_COPY_AND_ASSIGN (ModuleCompleter); + DISALLOW_COPY_AND_ASSIGN(ModuleCompleter); }; //---------------------------------------------------------------------- @@ -265,23 +264,22 @@ public: class SymbolCompleter : public Completer { public: - SymbolCompleter (CommandInterpreter &interpreter, const char *completion_str, int match_start_point, int max_return_elements, StringList &matches); - virtual Searcher::Depth GetDepth (); + Searcher::Depth GetDepth() override; - virtual Searcher::CallbackReturn - SearchCallback (SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool complete); + Searcher::CallbackReturn + SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) override; size_t - DoCompletion (SearchFilter *filter); + DoCompletion(SearchFilter *filter) override; private: // struct NameCmp { @@ -294,14 +292,14 @@ public: RegularExpression m_regex; typedef std::set collection; collection m_match_set; - DISALLOW_COPY_AND_ASSIGN (SymbolCompleter); + DISALLOW_COPY_AND_ASSIGN(SymbolCompleter); }; private: static CommonCompletionElement g_common_completions[]; - }; } // namespace lldb_private -#endif // lldb_CommandCompletions_h_ + +#endif // lldb_CommandCompletions_h_ diff --git a/include/lldb/Interpreter/CommandHistory.h b/include/lldb/Interpreter/CommandHistory.h index dbe6e99bb5b1..db5db15fc1e5 100644 --- a/include/lldb/Interpreter/CommandHistory.h +++ b/include/lldb/Interpreter/CommandHistory.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes - #include "lldb/lldb-private.h" #include "lldb/Core/Stream.h" #include "lldb/Host/Mutex.h" diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h index 1962050dffcb..dd5c189d0ab9 100644 --- a/include/lldb/Interpreter/CommandInterpreter.h +++ b/include/lldb/Interpreter/CommandInterpreter.h @@ -14,6 +14,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Debugger.h" @@ -199,8 +200,6 @@ class CommandInterpreter : public IOHandlerDelegate { public: - - typedef std::map OptionArgMap; enum @@ -228,11 +227,17 @@ public: eCommandTypesAllThem = 0xFFFF // all commands }; + CommandInterpreter(Debugger &debugger, + lldb::ScriptLanguage script_language, + bool synchronous_execution); + + ~CommandInterpreter() override; + // These two functions fill out the Broadcaster interface: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } @@ -241,13 +246,6 @@ public: SourceInitFile (bool in_cwd, CommandReturnObject &result); - CommandInterpreter (Debugger &debugger, - lldb::ScriptLanguage script_language, - bool synchronous_execution); - - virtual - ~CommandInterpreter (); - bool AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, @@ -267,8 +265,8 @@ public: bool include_aliases); CommandObject * - GetCommandObject (const char *cmd, - StringList *matches = NULL); + GetCommandObject(const char *cmd, + StringList *matches = nullptr); bool CommandExists (const char *cmd); @@ -305,7 +303,6 @@ public: OptionArgVectorSP GetAliasOptions (const char *alias_name); - bool ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, const char *options_args, @@ -325,20 +322,20 @@ public: CommandReturnObject &result); bool - HandleCommand (const char *command_line, - LazyBool add_to_history, - CommandReturnObject &result, - ExecutionContext *override_context = NULL, - bool repeat_on_empty_command = true, - bool no_context_switching = false); + HandleCommand(const char *command_line, + LazyBool add_to_history, + CommandReturnObject &result, + ExecutionContext *override_context = nullptr, + bool repeat_on_empty_command = true, + bool no_context_switching = false); //------------------------------------------------------------------ /// Execute a list of commands in sequence. /// /// @param[in] commands /// The list of commands to execute. - /// @param[in/out] context - /// The execution context in which to run the commands. Can be NULL in which case the default + /// @param[in,out] context + /// The execution context in which to run the commands. Can be nullptr in which case the default /// context will be used. /// @param[in] options /// This object holds the options used to control when to stop, whether to execute commands, @@ -358,8 +355,8 @@ public: /// /// @param[in] file /// The file from which to read in commands. - /// @param[in/out] context - /// The execution context in which to run the commands. Can be NULL in which case the default + /// @param[in,out] context + /// The execution context in which to run the commands. Can be nullptr in which case the default /// context will be used. /// @param[in] options /// This object holds the options used to control when to stop, whether to execute commands, @@ -393,7 +390,6 @@ public: // Otherwise, returns the number of matches. // // FIXME: Only max_return_elements == -1 is supported at present. - int HandleCompletion (const char *current_line, const char *cursor, @@ -406,7 +402,6 @@ public: // Help command can call it for the first argument. // word_complete tells whether the completions are considered a "complete" response (so the // completer should complete the quote & put a space after the word. - int HandleCompletionMatches (Args &input, int &cursor_index, @@ -416,7 +411,6 @@ public: bool &word_complete, StringList &matches); - int GetCommandNamesMatchingPartialString (const char *cmd_cstr, bool include_aliases, @@ -496,7 +490,6 @@ public: void SetScriptLanguage (lldb::ScriptLanguage lang); - bool HasCommands (); @@ -520,7 +513,10 @@ public: GetOptionArgumentPosition (const char *in_string); ScriptInterpreter * - GetScriptInterpreter (bool can_create = true); + GetScriptInterpreter(bool can_create = true); + + void + SetScriptInterpreter(); void SkipLLDBInitFiles (bool skip_lldbinit_files) @@ -647,7 +643,7 @@ public: } lldb::IOHandlerSP - GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = NULL); + GetIOHandler(bool force_create = false, CommandInterpreterRunOptions *options = nullptr); bool GetStoppedForCrash () const @@ -655,26 +651,29 @@ public: return m_stopped_for_crash; } + bool + GetSpaceReplPrompts () const; + protected: friend class Debugger; //------------------------------------------------------------------ // IOHandlerDelegate functions //------------------------------------------------------------------ - virtual void - IOHandlerInputComplete (IOHandler &io_handler, - std::string &line); + void + IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override; - virtual ConstString - IOHandlerGetControlSequence (char ch) + ConstString + IOHandlerGetControlSequence(char ch) override { if (ch == 'd') return ConstString("quit\n"); return ConstString(); } - virtual bool - IOHandlerInterrupt (IOHandler &io_handler); + bool + IOHandlerInterrupt(IOHandler &io_handler) override; size_t GetProcessOutput (); @@ -683,11 +682,9 @@ protected: SetSynchronous (bool value); lldb::CommandObjectSP - GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL); - + GetCommandSP(const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = nullptr); private: - Error PreprocessCommand (std::string &command); @@ -697,7 +694,6 @@ private: CommandObject * ResolveCommandImpl(std::string &command_line, CommandReturnObject &result); - Debugger &m_debugger; // The debugger session that this interpreter is associated with ExecutionContextRef m_exe_ctx_ref; // The current execution context to use when handling commands bool m_synchronous_execution; @@ -709,7 +705,7 @@ private: OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias. CommandHistory m_command_history; std::string m_repeat_command; // Stores the command that will be executed for an empty command string. - std::unique_ptr m_script_interpreter_ap; + lldb::ScriptInterpreterSP m_script_interpreter_sp; lldb::IOHandlerSP m_command_io_handler_sp; char m_comment_char; bool m_batch_command_mode; @@ -719,10 +715,8 @@ private: uint32_t m_num_errors; bool m_quit_requested; bool m_stopped_for_crash; - }; - } // namespace lldb_private -#endif // liblldb_CommandInterpreter_h_ +#endif // liblldb_CommandInterpreter_h_ diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h index 023de29c7b6c..8015fec41cd2 100644 --- a/include/lldb/Interpreter/CommandObject.h +++ b/include/lldb/Interpreter/CommandObject.h @@ -10,11 +10,14 @@ #ifndef liblldb_CommandObject_h_ #define liblldb_CommandObject_h_ +// C Includes +// C++ Includes #include -#include #include #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandCompletions.h" @@ -28,7 +31,6 @@ namespace lldb_private { class CommandObject { public: - typedef const char *(ArgumentHelpCallbackFunction) (); struct ArgumentHelpCallback @@ -44,9 +46,8 @@ public: explicit operator bool() const { - return (help_callback != NULL); + return (help_callback != nullptr); } - }; struct ArgumentTableEntry // Entries in the main argument information table @@ -76,16 +77,15 @@ public: typedef std::map CommandMap; - CommandObject (CommandInterpreter &interpreter, - const char *name, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0); + CommandObject(CommandInterpreter &interpreter, + const char *name, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0); virtual ~CommandObject (); - static const char * GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type); @@ -141,15 +141,15 @@ public: IsMultiwordObject () { return false; } virtual lldb::CommandObjectSP - GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL) + GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) { return lldb::CommandObjectSP(); } virtual CommandObject * - GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL) + GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) { - return NULL; + return nullptr; } virtual void @@ -326,7 +326,6 @@ public: /// @return /// The number of completions. //------------------------------------------------------------------ - virtual int HandleArgumentCompletion (Args &input, int &cursor_index, @@ -374,13 +373,13 @@ public: /// The complete current command line. /// /// @return - /// NULL if there is no special repeat command - it will use the current command line. + /// nullptr if there is no special repeat command - it will use the current command line. /// Otherwise a pointer to the command to be repeated. /// If the returned string is the empty string, the command won't be repeated. //------------------------------------------------------------------ virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) { - return NULL; + return nullptr; } bool @@ -488,62 +487,61 @@ protected: // to the specified command argument entry. static void AddIDsArgumentData(CommandArgumentEntry &arg, lldb::CommandArgumentType ID, lldb::CommandArgumentType IDRange); - }; class CommandObjectParsed : public CommandObject { public: - - CommandObjectParsed (CommandInterpreter &interpreter, - const char *name, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0) : + CommandObjectParsed(CommandInterpreter &interpreter, + const char *name, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0) : CommandObject (interpreter, name, help, syntax, flags) {} - virtual - ~CommandObjectParsed () {}; + ~CommandObjectParsed() override = default; - virtual bool - Execute (const char *args_string, CommandReturnObject &result); + bool + Execute(const char *args_string, CommandReturnObject &result) override; protected: virtual bool DoExecute (Args& command, CommandReturnObject &result) = 0; - virtual bool - WantsRawCommandString() { return false; }; + bool + WantsRawCommandString() override + { + return false; + } }; class CommandObjectRaw : public CommandObject { public: - - CommandObjectRaw (CommandInterpreter &interpreter, - const char *name, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0) : + CommandObjectRaw(CommandInterpreter &interpreter, + const char *name, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0) : CommandObject (interpreter, name, help, syntax, flags) {} - virtual - ~CommandObjectRaw () {}; + ~CommandObjectRaw() override = default; - virtual bool - Execute (const char *args_string, CommandReturnObject &result); + bool + Execute(const char *args_string, CommandReturnObject &result) override; protected: virtual bool DoExecute (const char *command, CommandReturnObject &result) = 0; - virtual bool - WantsRawCommandString() { return true; }; + bool + WantsRawCommandString() override + { + return true; + } }; - } // namespace lldb_private - -#endif // liblldb_CommandObject_h_ +#endif // liblldb_CommandObject_h_ diff --git a/include/lldb/Interpreter/CommandObjectMultiword.h b/include/lldb/Interpreter/CommandObjectMultiword.h index 491d43c4bd9d..e1ad2940c383 100644 --- a/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/include/lldb/Interpreter/CommandObjectMultiword.h @@ -12,8 +12,6 @@ // C Includes // C++ Includes -#include - // Other libraries and framework includes // Project includes #include "lldb/Interpreter/CommandObject.h" @@ -30,57 +28,66 @@ class CommandObjectMultiword : public CommandObject friend class CommandInterpreter; friend class CommandObjectSyntax; public: - CommandObjectMultiword (CommandInterpreter &interpreter, - const char *name, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0); + CommandObjectMultiword(CommandInterpreter &interpreter, + const char *name, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0); - virtual - ~CommandObjectMultiword (); + ~CommandObjectMultiword() override; - virtual bool - IsMultiwordObject () { return true; } + bool + IsMultiwordObject() override + { + return true; + } - virtual bool - LoadSubCommand (const char *cmd_name, - const lldb::CommandObjectSP& command_obj); + bool + LoadSubCommand(const char *cmd_name, + const lldb::CommandObjectSP& command_obj) override; - virtual void - GenerateHelpText (Stream &output_stream); + void + GenerateHelpText(Stream &output_stream) override; - virtual lldb::CommandObjectSP - GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL); + lldb::CommandObjectSP + GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override; - virtual CommandObject * - GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL); - - virtual void - AproposAllSubCommands (const char *prefix, - const char *search_word, - StringList &commands_found, - StringList &commands_help); - - virtual bool - WantsRawCommandString() { return false; }; - - virtual int - HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); - - virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index); - - virtual bool - Execute (const char *args_string, - CommandReturnObject &result); + CommandObject * + GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override; + + void + AproposAllSubCommands(const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help) override; + + bool + WantsRawCommandString() override + { + return false; + } + + int + HandleCompletion(Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + const char * + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override; + + bool + Execute(const char *args_string, + CommandReturnObject &result) override; - virtual bool - IsRemovable() const { return m_can_be_removed; } + bool + IsRemovable() const override + { + return m_can_be_removed; + } void SetRemovable (bool removable) @@ -93,95 +100,93 @@ protected: CommandObject::CommandMap m_subcommand_dict; bool m_can_be_removed; }; - class CommandObjectProxy : public CommandObject { public: - CommandObjectProxy (CommandInterpreter &interpreter, - const char *name, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0); + CommandObjectProxy(CommandInterpreter &interpreter, + const char *name, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0); - virtual - ~CommandObjectProxy (); + ~CommandObjectProxy() override; // Subclasses must provide a command object that will be transparently // used for this object. virtual CommandObject * GetProxyCommandObject() = 0; - virtual const char * - GetHelpLong (); + const char * + GetHelpLong() override; - virtual bool - IsRemovable() const; + bool + IsRemovable() const override; - virtual bool - IsMultiwordObject (); - - virtual lldb::CommandObjectSP - GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL); - - virtual CommandObject * - GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL); + bool + IsMultiwordObject() override; - virtual void - AproposAllSubCommands (const char *prefix, - const char *search_word, - StringList &commands_found, - StringList &commands_help); - - virtual bool - LoadSubCommand (const char *cmd_name, - const lldb::CommandObjectSP& command_obj); - - virtual bool - WantsRawCommandString(); + void + GenerateHelpText (Stream &result) override; - virtual bool - WantsCompletion(); + lldb::CommandObjectSP + GetSubcommandSP(const char *sub_cmd, StringList *matches = nullptr) override; - virtual Options * - GetOptions (); + CommandObject * + GetSubcommandObject(const char *sub_cmd, StringList *matches = nullptr) override; - - virtual int - HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); - - virtual int - HandleArgumentCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - OptionElementVector &opt_element_vector, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); - - virtual const char * - GetRepeatCommand (Args ¤t_command_args, - uint32_t index); - - virtual bool - Execute (const char *args_string, - CommandReturnObject &result); + void + AproposAllSubCommands(const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help) override; + + bool + LoadSubCommand(const char *cmd_name, + const lldb::CommandObjectSP& command_obj) override; + + bool + WantsRawCommandString() override; + + bool + WantsCompletion() override; + + Options * + GetOptions() override; + + int + HandleCompletion(Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + int + HandleArgumentCompletion(Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; + + const char * + GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override; + + bool + Execute(const char *args_string, + CommandReturnObject &result) override; protected: - // These two want to iterate over the subcommand dictionary. friend class CommandInterpreter; friend class CommandObjectSyntax; - }; } // namespace lldb_private -#endif // liblldb_CommandObjectMultiword_h_ +#endif // liblldb_CommandObjectMultiword_h_ diff --git a/include/lldb/Interpreter/CommandObjectRegexCommand.h b/include/lldb/Interpreter/CommandObjectRegexCommand.h index d86544638776..9f8974a32bb2 100644 --- a/include/lldb/Interpreter/CommandObjectRegexCommand.h +++ b/include/lldb/Interpreter/CommandObjectRegexCommand.h @@ -28,7 +28,6 @@ namespace lldb_private { class CommandObjectRegexCommand : public CommandObjectRaw { public: - CommandObjectRegexCommand (CommandInterpreter &interpreter, const char *name, const char *help, @@ -37,8 +36,7 @@ public: uint32_t completion_type_mask, bool is_removable); - virtual - ~CommandObjectRegexCommand (); + ~CommandObjectRegexCommand() override; bool IsRemovable () const override { return m_is_removable; } @@ -83,4 +81,4 @@ private: } // namespace lldb_private -#endif // liblldb_CommandObjectRegexCommand_h_ +#endif // liblldb_CommandObjectRegexCommand_h_ diff --git a/include/lldb/Interpreter/CommandOptionValidators.h b/include/lldb/Interpreter/CommandOptionValidators.h index 6be247ad4b65..395cb8ed3d9e 100644 --- a/include/lldb/Interpreter/CommandOptionValidators.h +++ b/include/lldb/Interpreter/CommandOptionValidators.h @@ -10,6 +10,10 @@ #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 { @@ -19,12 +23,11 @@ class ExecutionContext; class PosixPlatformCommandOptionValidator : public OptionValidator { - virtual bool IsValid(Platform &platform, const ExecutionContext &target) const; - virtual const char* ShortConditionString() const; - virtual const char* LongConditionString() const; + bool IsValid(Platform &platform, const ExecutionContext &target) const override; + const char* ShortConditionString() const override; + const char* LongConditionString() const override; }; } // namespace lldb_private - -#endif // liblldb_CommandOptionValidators_h_ +#endif // liblldb_CommandOptionValidators_h_ diff --git a/include/lldb/Interpreter/CommandReturnObject.h b/include/lldb/Interpreter/CommandReturnObject.h index b922e1731d7e..424ac800d14c 100644 --- a/include/lldb/Interpreter/CommandReturnObject.h +++ b/include/lldb/Interpreter/CommandReturnObject.h @@ -22,11 +22,9 @@ namespace lldb_private { - class CommandReturnObject { public: - CommandReturnObject (); ~CommandReturnObject (); @@ -142,8 +140,8 @@ public: AppendErrorWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); void - SetError (const Error &error, - const char *fallback_error_cstr = NULL); + SetError(const Error &error, + const char *fallback_error_cstr = nullptr); void SetError (const char *error_cstr); @@ -189,4 +187,4 @@ private: } // namespace lldb_private -#endif // liblldb_CommandReturnObject_h_ +#endif // liblldb_CommandReturnObject_h_ diff --git a/include/lldb/Interpreter/OptionGroupArchitecture.h b/include/lldb/Interpreter/OptionGroupArchitecture.h index 7cd1ca3d710d..5ee608506c04 100644 --- a/include/lldb/Interpreter/OptionGroupArchitecture.h +++ b/include/lldb/Interpreter/OptionGroupArchitecture.h @@ -26,26 +26,23 @@ namespace lldb_private { class OptionGroupArchitecture : public OptionGroup { public: - OptionGroupArchitecture (); - virtual - ~OptionGroupArchitecture (); + ~OptionGroupArchitecture() override; + uint32_t + GetNumDefinitions() override; - virtual uint32_t - GetNumDefinitions (); - - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; bool GetArchitecture (Platform *platform, ArchSpec &arch); @@ -55,19 +52,17 @@ public: { return !m_arch_str.empty(); } + const char * - GetArchitectureName () + GetArchitectureName() { - if (m_arch_str.empty()) - return NULL; - return m_arch_str.c_str(); + return (m_arch_str.empty() ? nullptr : m_arch_str.c_str()); } protected: - std::string m_arch_str; // Save the arch triple in case a platform is specified after the architecture }; } // namespace lldb_private -#endif // liblldb_OptionGroupArchitecture_h_ +#endif // liblldb_OptionGroupArchitecture_h_ diff --git a/include/lldb/Interpreter/OptionGroupBoolean.h b/include/lldb/Interpreter/OptionGroupBoolean.h index 0d861b241694..881a1bdf4be6 100644 --- a/include/lldb/Interpreter/OptionGroupBoolean.h +++ b/include/lldb/Interpreter/OptionGroupBoolean.h @@ -36,29 +36,27 @@ namespace lldb_private { bool default_value, bool no_argument_toggle_default); - virtual - ~OptionGroupBoolean (); - - - virtual uint32_t - GetNumDefinitions () + ~OptionGroupBoolean() override; + + uint32_t + GetNumDefinitions() override { return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions() override { return &m_option_definition; } - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; OptionValueBoolean & GetOptionValue () @@ -75,9 +73,8 @@ namespace lldb_private { protected: OptionValueBoolean m_value; OptionDefinition m_option_definition; - }; } // namespace lldb_private -#endif // liblldb_OptionGroupBoolean_h_ +#endif // liblldb_OptionGroupBoolean_h_ diff --git a/include/lldb/Interpreter/OptionGroupFile.h b/include/lldb/Interpreter/OptionGroupFile.h index 632a2dbdf220..9e35dd43ab7a 100644 --- a/include/lldb/Interpreter/OptionGroupFile.h +++ b/include/lldb/Interpreter/OptionGroupFile.h @@ -1,4 +1,4 @@ -//===-- OptionGroupFile.h -------------------------------*- C++ -*-===// +//===-- OptionGroupFile.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -27,7 +27,6 @@ namespace lldb_private { class OptionGroupFile : public OptionGroup { public: - OptionGroupFile (uint32_t usage_mask, bool required, const char *long_option, @@ -36,29 +35,27 @@ public: lldb::CommandArgumentType argument_type, const char *usage_text); - virtual - ~OptionGroupFile (); + ~OptionGroupFile() override; - - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions() override { return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions() override { return &m_option_definition; } - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; OptionValueFileSpec & GetOptionValue () @@ -75,7 +72,6 @@ public: protected: OptionValueFileSpec m_file; OptionDefinition m_option_definition; - }; //------------------------------------------------------------------------- @@ -94,30 +90,27 @@ public: lldb::CommandArgumentType argument_type, const char *usage_text); - virtual - ~OptionGroupFileList (); + ~OptionGroupFileList() override; - - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions() override { return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions() override { return &m_option_definition; } - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); - - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; + void + OptionParsingStarting(CommandInterpreter &interpreter) override; OptionValueFileSpecList & GetOptionValue () @@ -134,9 +127,8 @@ public: protected: OptionValueFileSpecList m_file_list; OptionDefinition m_option_definition; - }; } // namespace lldb_private -#endif // liblldb_OptionGroupFile_h_ +#endif // liblldb_OptionGroupFile_h_ diff --git a/include/lldb/Interpreter/OptionGroupFormat.h b/include/lldb/Interpreter/OptionGroupFormat.h index 7419b0496668..9a96cc505de4 100644 --- a/include/lldb/Interpreter/OptionGroupFormat.h +++ b/include/lldb/Interpreter/OptionGroupFormat.h @@ -1,4 +1,4 @@ -//===-- OptionGroupFormat.h -------------------------------*- C++ -*-===// +//===-- OptionGroupFormat.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -37,23 +37,21 @@ public: uint64_t default_byte_size = UINT64_MAX, // Pass UINT64_MAX to disable the "--size" option uint64_t default_count = UINT64_MAX); // Pass UINT64_MAX to disable the "--count" option - virtual - ~OptionGroupFormat (); + ~OptionGroupFormat() override; + uint32_t + GetNumDefinitions() override; - virtual uint32_t - GetNumDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual const OptionDefinition* - GetDefinitions (); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); - - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; lldb::Format GetFormat () const @@ -112,7 +110,6 @@ public: } protected: - bool ParserGDBFormatLetter (CommandInterpreter &interpreter, char format_letter, @@ -124,10 +121,9 @@ protected: OptionValueUInt64 m_count; char m_prev_gdb_format; char m_prev_gdb_size; - bool m_has_gdb_format; }; } // namespace lldb_private -#endif // liblldb_OptionGroupFormat_h_ +#endif // liblldb_OptionGroupFormat_h_ diff --git a/include/lldb/Interpreter/OptionGroupOutputFile.h b/include/lldb/Interpreter/OptionGroupOutputFile.h index 533cd6ee8eb3..e6083714c48d 100644 --- a/include/lldb/Interpreter/OptionGroupOutputFile.h +++ b/include/lldb/Interpreter/OptionGroupOutputFile.h @@ -1,4 +1,4 @@ -//===-- OptionGroupOutputFile.h -------------------------------*- C++ -*-===// +//===-- OptionGroupOutputFile.h ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,26 +26,23 @@ namespace lldb_private { class OptionGroupOutputFile : public OptionGroup { public: - OptionGroupOutputFile (); - virtual - ~OptionGroupOutputFile (); + ~OptionGroupOutputFile() override; + uint32_t + GetNumDefinitions() override; - virtual uint32_t - GetNumDefinitions (); - - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; const OptionValueFileSpec & GetFile () @@ -68,9 +65,8 @@ public: protected: OptionValueFileSpec m_file; OptionValueBoolean m_append; - }; } // namespace lldb_private -#endif // liblldb_OptionGroupOutputFile_h_ +#endif // liblldb_OptionGroupOutputFile_h_ diff --git a/include/lldb/Interpreter/OptionGroupPlatform.h b/include/lldb/Interpreter/OptionGroupPlatform.h index f7de50c86a56..68880236accc 100644 --- a/include/lldb/Interpreter/OptionGroupPlatform.h +++ b/include/lldb/Interpreter/OptionGroupPlatform.h @@ -27,7 +27,6 @@ namespace lldb_private { class OptionGroupPlatform : public OptionGroup { public: - OptionGroupPlatform (bool include_platform_option) : OptionGroup(), m_platform_name (), @@ -39,24 +38,21 @@ public: { } - virtual - ~OptionGroupPlatform () - { - } + ~OptionGroupPlatform() override = default; - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; lldb::PlatformSP CreatePlatformWithOptions (CommandInterpreter &interpreter, @@ -119,4 +115,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionGroupPlatform_h_ +#endif // liblldb_OptionGroupPlatform_h_ diff --git a/include/lldb/Interpreter/OptionGroupString.h b/include/lldb/Interpreter/OptionGroupString.h index e62a81bc4118..6f46bdb79408 100644 --- a/include/lldb/Interpreter/OptionGroupString.h +++ b/include/lldb/Interpreter/OptionGroupString.h @@ -1,4 +1,4 @@ -//===-- OptionGroupString.h ------------------------------------*- C++ -*-===// +//===-- OptionGroupString.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,7 +25,6 @@ namespace lldb_private { class OptionGroupString : public OptionGroup { public: - OptionGroupString (uint32_t usage_mask, bool required, const char *long_option, @@ -35,29 +34,27 @@ namespace lldb_private { const char *usage_text, const char *default_value); - virtual - ~OptionGroupString (); - - - virtual uint32_t - GetNumDefinitions () + ~OptionGroupString() override; + + uint32_t + GetNumDefinitions() override { return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions() override { return &m_option_definition; } - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; OptionValueString & GetOptionValue () @@ -74,9 +71,8 @@ namespace lldb_private { protected: OptionValueString m_value; OptionDefinition m_option_definition; - }; } // namespace lldb_private -#endif // liblldb_OptionGroupString_h_ +#endif // liblldb_OptionGroupString_h_ diff --git a/include/lldb/Interpreter/OptionGroupUInt64.h b/include/lldb/Interpreter/OptionGroupUInt64.h index c5f9e85d2f8f..b03c1ff889a1 100644 --- a/include/lldb/Interpreter/OptionGroupUInt64.h +++ b/include/lldb/Interpreter/OptionGroupUInt64.h @@ -1,4 +1,4 @@ -//===-- OptionGroupUInt64.h ------------------------------------*- C++ -*-===// +//===-- OptionGroupUInt64.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "lldb/Interpreter/OptionValueUInt64.h" namespace lldb_private { + //------------------------------------------------------------------------- // OptionGroupUInt64 //------------------------------------------------------------------------- @@ -25,7 +26,6 @@ namespace lldb_private { class OptionGroupUInt64 : public OptionGroup { public: - OptionGroupUInt64 (uint32_t usage_mask, bool required, const char *long_option, @@ -35,29 +35,27 @@ namespace lldb_private { const char *usage_text, uint64_t default_value); - virtual - ~OptionGroupUInt64 (); - - - virtual uint32_t - GetNumDefinitions () + ~OptionGroupUInt64() override; + + uint32_t + GetNumDefinitions() override { return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions() override { return &m_option_definition; } - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; OptionValueUInt64 & GetOptionValue () @@ -74,9 +72,8 @@ namespace lldb_private { protected: OptionValueUInt64 m_value; OptionDefinition m_option_definition; - }; } // namespace lldb_private -#endif // liblldb_OptionGroupUInt64_h_ +#endif // liblldb_OptionGroupUInt64_h_ diff --git a/include/lldb/Interpreter/OptionGroupUUID.h b/include/lldb/Interpreter/OptionGroupUUID.h index ea968d737969..6495699dce75 100644 --- a/include/lldb/Interpreter/OptionGroupUUID.h +++ b/include/lldb/Interpreter/OptionGroupUUID.h @@ -18,6 +18,7 @@ #include "lldb/Interpreter/OptionValueUUID.h" namespace lldb_private { + //------------------------------------------------------------------------- // OptionGroupUUID //------------------------------------------------------------------------- @@ -25,26 +26,23 @@ namespace lldb_private { class OptionGroupUUID : public OptionGroup { public: - OptionGroupUUID (); - virtual - ~OptionGroupUUID (); + ~OptionGroupUUID() override; + uint32_t + GetNumDefinitions() override; - virtual uint32_t - GetNumDefinitions (); - - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; const OptionValueUUID & GetOptionValue () const @@ -58,4 +56,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionGroupUUID_h_ +#endif // liblldb_OptionGroupUUID_h_ diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h index 5cce126f89bf..53c8550da81e 100644 --- a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h +++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -1,4 +1,4 @@ -//===-- OptionGroupValueObjectDisplay.h -------------------------------*- C++ -*-===// +//===-- OptionGroupValueObjectDisplay.h -------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,41 +26,38 @@ namespace lldb_private { class OptionGroupValueObjectDisplay : public OptionGroup { public: - OptionGroupValueObjectDisplay (); - virtual - ~OptionGroupValueObjectDisplay (); + ~OptionGroupValueObjectDisplay() override; + uint32_t + GetNumDefinitions() override; - virtual uint32_t - GetNumDefinitions (); - - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; bool AnyOptionWasSet () const { - return show_types == true || - no_summary_depth != 0 || - show_location == true || - flat_output == true || - use_objc == true || + return show_types || + no_summary_depth != 0 || + show_location || + flat_output || + use_objc || max_depth != UINT32_MAX || ptr_depth != 0 || - use_synth == false || - be_raw == true || - ignore_cap == true || - run_validator == true; + !use_synth || + be_raw || + ignore_cap || + run_validator; } DumpValueObjectOptions @@ -85,4 +82,4 @@ public: } // namespace lldb_private -#endif // liblldb_OptionGroupValueObjectDisplay_h_ +#endif // liblldb_OptionGroupValueObjectDisplay_h_ diff --git a/include/lldb/Interpreter/OptionGroupVariable.h b/include/lldb/Interpreter/OptionGroupVariable.h index 40f4d436bc69..fd338f1ba8cb 100644 --- a/include/lldb/Interpreter/OptionGroupVariable.h +++ b/include/lldb/Interpreter/OptionGroupVariable.h @@ -26,25 +26,23 @@ namespace lldb_private { class OptionGroupVariable : public OptionGroup { public: - OptionGroupVariable (bool show_frame_options); - virtual - ~OptionGroupVariable (); - - virtual uint32_t - GetNumDefinitions (); + ~OptionGroupVariable() override; + + uint32_t + GetNumDefinitions() override; - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_arg); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; bool include_frame_options:1, show_args:1, // Frame option only (include_frame_options == true) @@ -62,4 +60,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // liblldb_OptionGroupVariable_h_ +#endif // liblldb_OptionGroupVariable_h_ diff --git a/include/lldb/Interpreter/OptionGroupWatchpoint.h b/include/lldb/Interpreter/OptionGroupWatchpoint.h index 1298da80750e..ddc4393bdc25 100644 --- a/include/lldb/Interpreter/OptionGroupWatchpoint.h +++ b/include/lldb/Interpreter/OptionGroupWatchpoint.h @@ -25,28 +25,26 @@ namespace lldb_private { class OptionGroupWatchpoint : public OptionGroup { public: - + OptionGroupWatchpoint (); + + ~OptionGroupWatchpoint() override; + static bool IsWatchSizeSupported(uint32_t watch_size); - OptionGroupWatchpoint (); - - virtual - ~OptionGroupWatchpoint (); - - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_arg); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; // Note: // eWatchRead == LLDB_WATCH_TYPE_READ; and @@ -68,4 +66,4 @@ namespace lldb_private { } // namespace lldb_private -#endif // liblldb_OptionGroupWatchpoint_h_ +#endif // liblldb_OptionGroupWatchpoint_h_ diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h index fd751f744de6..a05a0fb0b64f 100644 --- a/include/lldb/Interpreter/OptionValue.h +++ b/include/lldb/Interpreter/OptionValue.h @@ -1,4 +1,4 @@ -//===-- OptionValue.h --------------------------------------*- C++ -*-===// +//===-- OptionValue.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -61,7 +61,6 @@ namespace lldb_private { eDumpGroupHelp = (eDumpOptionName | eDumpOptionType | eDumpOptionDescription) }; - OptionValue () : m_callback (nullptr), m_baton(nullptr), @@ -76,9 +75,8 @@ namespace lldb_private { { } - virtual ~OptionValue () - { - } + virtual ~OptionValue() = default; + //----------------------------------------------------------------- // Subclasses should override these functions //----------------------------------------------------------------- @@ -99,7 +97,6 @@ namespace lldb_private { return GetBuiltinTypeAsCString(GetType()); } - static const char * GetBuiltinTypeAsCString (Type t); @@ -156,6 +153,7 @@ namespace lldb_private { virtual bool DumpQualifiedName (Stream &strm) const; + //----------------------------------------------------------------- // Subclasses should NOT override these functions as they use the // above functions to implement functionality @@ -376,7 +374,7 @@ namespace lldb_private { SetSInt64Value (int64_t new_value); const char * - GetStringValue (const char *fail_value = NULL) const; + GetStringValue(const char *fail_value = nullptr) const; bool SetStringValue (const char *new_value); @@ -415,7 +413,7 @@ namespace lldb_private { SetValueChangedCallback (OptionValueChangedCallback callback, void *baton) { - assert (m_callback == NULL); + assert (m_callback == nullptr); m_callback = callback; m_baton = baton; } @@ -426,6 +424,7 @@ namespace lldb_private { if (m_callback) m_callback (m_baton, this); } + protected: lldb::OptionValueWP m_parent_wp; OptionValueChangedCallback m_callback; @@ -436,9 +435,8 @@ namespace lldb_private { // the command line or as a setting, versus if we // just have the default value that was already // populated in the option value. - }; } // namespace lldb_private -#endif // liblldb_OptionValue_h_ +#endif // liblldb_OptionValue_h_ diff --git a/include/lldb/Interpreter/OptionValueArch.h b/include/lldb/Interpreter/OptionValueArch.h index 3d5d72619efc..c83dc8558084 100644 --- a/include/lldb/Interpreter/OptionValueArch.h +++ b/include/lldb/Interpreter/OptionValueArch.h @@ -52,8 +52,7 @@ public: { } - virtual - ~OptionValueArch() + ~OptionValueArch() override { } @@ -61,37 +60,37 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeArch; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual size_t - AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + size_t + AutoComplete(CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; //--------------------------------------------------------------------- // Subclass specific functions @@ -136,4 +135,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueArch_h_ +#endif // liblldb_OptionValueArch_h_ diff --git a/include/lldb/Interpreter/OptionValueArgs.h b/include/lldb/Interpreter/OptionValueArgs.h index 365a52a8b39f..ad9505af3015 100644 --- a/include/lldb/Interpreter/OptionValueArgs.h +++ b/include/lldb/Interpreter/OptionValueArgs.h @@ -26,16 +26,15 @@ public: { } - virtual - ~OptionValueArgs() + ~OptionValueArgs() override { } size_t GetArgs (Args &args); - virtual Type - GetType() const + Type + GetType() const override { return eTypeArgs; } @@ -43,4 +42,4 @@ public: } // namespace lldb_private -#endif // liblldb_OptionValueArgs_h_ +#endif // liblldb_OptionValueArgs_h_ diff --git a/include/lldb/Interpreter/OptionValueArray.h b/include/lldb/Interpreter/OptionValueArray.h index 2e44f9f07438..38b9e3c3ee97 100644 --- a/include/lldb/Interpreter/OptionValueArray.h +++ b/include/lldb/Interpreter/OptionValueArray.h @@ -30,8 +30,7 @@ public: { } - virtual - ~OptionValueArray() + ~OptionValueArray() override { } @@ -39,41 +38,41 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeArray; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_values.clear(); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual bool - IsAggregateValue () const + bool + IsAggregateValue() const override { return true; } - virtual lldb::OptionValueSP - GetSubValue (const ExecutionContext *exe_ctx, - const char *name, - bool will_modify, - Error &error) const; + lldb::OptionValueSP + GetSubValue(const ExecutionContext *exe_ctx, + const char *name, + bool will_modify, + Error &error) const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -175,4 +174,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueArray_h_ +#endif // liblldb_OptionValueArray_h_ diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h index 214fd1649d39..52d39a9b8d27 100644 --- a/include/lldb/Interpreter/OptionValueBoolean.h +++ b/include/lldb/Interpreter/OptionValueBoolean.h @@ -35,8 +35,7 @@ public: { } - virtual - ~OptionValueBoolean() + ~OptionValueBoolean() override { } @@ -44,34 +43,34 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeBoolean; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual size_t - AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + size_t + AutoComplete(CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; //--------------------------------------------------------------------- // Subclass specific functions @@ -128,8 +127,8 @@ public: m_default_value = value; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; protected: bool m_current_value; @@ -138,4 +137,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueBoolean_h_ +#endif // liblldb_OptionValueBoolean_h_ diff --git a/include/lldb/Interpreter/OptionValueChar.h b/include/lldb/Interpreter/OptionValueChar.h index 8fc02093e3d9..b05d9ca098b2 100644 --- a/include/lldb/Interpreter/OptionValueChar.h +++ b/include/lldb/Interpreter/OptionValueChar.h @@ -27,6 +27,7 @@ public: m_default_value (value) { } + OptionValueChar (char current_value, char default_value) : OptionValue(), @@ -35,8 +36,7 @@ public: { } - virtual - ~OptionValueChar() + ~OptionValueChar() override { } @@ -44,21 +44,21 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeChar; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; @@ -100,8 +100,8 @@ public: m_default_value = value; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; protected: char m_current_value; @@ -110,4 +110,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueChar_h_ +#endif // liblldb_OptionValueChar_h_ diff --git a/include/lldb/Interpreter/OptionValueDictionary.h b/include/lldb/Interpreter/OptionValueDictionary.h index efa15dd6ef88..8ee839775646 100644 --- a/include/lldb/Interpreter/OptionValueDictionary.h +++ b/include/lldb/Interpreter/OptionValueDictionary.h @@ -31,8 +31,7 @@ public: { } - virtual - ~OptionValueDictionary() + ~OptionValueDictionary() override { } @@ -40,32 +39,32 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeDictionary; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_values.clear(); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual bool - IsAggregateValue () const + bool + IsAggregateValue() const override { return true; } @@ -89,17 +88,17 @@ public: lldb::OptionValueSP GetValueForKey (const ConstString &key) const; - virtual lldb::OptionValueSP - GetSubValue (const ExecutionContext *exe_ctx, - const char *name, - bool will_modify, - Error &error) const; - - virtual Error - SetSubValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *name, - const char *value); + lldb::OptionValueSP + GetSubValue(const ExecutionContext *exe_ctx, + const char *name, + bool will_modify, + Error &error) const override; + + Error + SetSubValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *name, + const char *value) override; //--------------------------------------------------------------------- // String value getters and setters @@ -136,4 +135,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueDictionary_h_ +#endif // liblldb_OptionValueDictionary_h_ diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h index e820729385de..b3fc481dd7fa 100644 --- a/include/lldb/Interpreter/OptionValueEnumeration.h +++ b/include/lldb/Interpreter/OptionValueEnumeration.h @@ -23,7 +23,6 @@ namespace lldb_private { - class OptionValueEnumeration : public OptionValue { public: @@ -38,44 +37,43 @@ public: OptionValueEnumeration (const OptionEnumValueElement *enumerators, enum_type value); - virtual - ~OptionValueEnumeration(); + ~OptionValueEnumeration() override; //--------------------------------------------------------------------- // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeEnum; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual size_t - AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + size_t + AutoComplete(CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; //--------------------------------------------------------------------- // Subclass specific functions @@ -123,4 +121,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueEnumeration_h_ +#endif // liblldb_OptionValueEnumeration_h_ diff --git a/include/lldb/Interpreter/OptionValueFileSpec.h b/include/lldb/Interpreter/OptionValueFileSpec.h index 80dd77ecef2a..274c4d064e51 100644 --- a/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/include/lldb/Interpreter/OptionValueFileSpec.h @@ -31,8 +31,7 @@ public: const FileSpec &default_value, bool resolve = true); - virtual - ~OptionValueFileSpec() + ~OptionValueFileSpec() override { } @@ -40,21 +39,21 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeFileSpec; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; @@ -63,16 +62,16 @@ public: return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual size_t - AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + size_t + AutoComplete(CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; //--------------------------------------------------------------------- // Subclass specific functions @@ -131,4 +130,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueFileSpec_h_ +#endif // liblldb_OptionValueFileSpec_h_ diff --git a/include/lldb/Interpreter/OptionValueFileSpecList.h b/include/lldb/Interpreter/OptionValueFileSpecList.h index a105d22e45f9..205132358024 100644 --- a/include/lldb/Interpreter/OptionValueFileSpecList.h +++ b/include/lldb/Interpreter/OptionValueFileSpecList.h @@ -34,9 +34,7 @@ public: { } - - virtual - ~OptionValueFileSpecList() + ~OptionValueFileSpecList() override { } @@ -44,32 +42,32 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeFileSpecList; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value.Clear(); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual bool - IsAggregateValue () const + bool + IsAggregateValue() const override { return true; } @@ -102,4 +100,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueFileSpecList_h_ +#endif // liblldb_OptionValueFileSpecList_h_ diff --git a/include/lldb/Interpreter/OptionValueFormat.h b/include/lldb/Interpreter/OptionValueFormat.h index 06ed12854318..1c2909459911 100644 --- a/include/lldb/Interpreter/OptionValueFormat.h +++ b/include/lldb/Interpreter/OptionValueFormat.h @@ -36,8 +36,7 @@ public: { } - virtual - ~OptionValueFormat() + ~OptionValueFormat() override { } @@ -45,29 +44,29 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeFormat; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -104,4 +103,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueFormat_h_ +#endif // liblldb_OptionValueFormat_h_ diff --git a/include/lldb/Interpreter/OptionValueFormatEntity.h b/include/lldb/Interpreter/OptionValueFormatEntity.h index 18ace3a6a1b6..10a456a1b994 100644 --- a/include/lldb/Interpreter/OptionValueFormatEntity.h +++ b/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -24,8 +24,7 @@ class OptionValueFormatEntity : public OptionValue public: OptionValueFormatEntity (const char *default_format); - virtual - ~OptionValueFormatEntity() + ~OptionValueFormatEntity() override { } @@ -94,7 +93,6 @@ public: return m_default_entry; } - protected: std::string m_current_format; std::string m_default_format; @@ -104,4 +102,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueFormatEntity_h_ +#endif // liblldb_OptionValueFormatEntity_h_ diff --git a/include/lldb/Interpreter/OptionValueLanguage.h b/include/lldb/Interpreter/OptionValueLanguage.h index fba5e22821e0..bd6df3ea4943 100644 --- a/include/lldb/Interpreter/OptionValueLanguage.h +++ b/include/lldb/Interpreter/OptionValueLanguage.h @@ -37,8 +37,7 @@ public: { } - virtual - ~OptionValueLanguage () + ~OptionValueLanguage() override { } @@ -104,4 +103,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueLanguage_h_ +#endif // liblldb_OptionValueLanguage_h_ diff --git a/include/lldb/Interpreter/OptionValuePathMappings.h b/include/lldb/Interpreter/OptionValuePathMappings.h index 7b476a9cd366..4ed1c8c848d6 100644 --- a/include/lldb/Interpreter/OptionValuePathMappings.h +++ b/include/lldb/Interpreter/OptionValuePathMappings.h @@ -29,8 +29,7 @@ public: { } - virtual - ~OptionValuePathMappings() + ~OptionValuePathMappings() override { } @@ -38,32 +37,32 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypePathMap; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_path_mappings.Clear(m_notify_changes); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual bool - IsAggregateValue () const + bool + IsAggregateValue() const override { return true; } @@ -91,4 +90,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValuePathMappings_h_ +#endif // liblldb_OptionValuePathMappings_h_ diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h index 405beefff6d1..c8783bcf36eb 100644 --- a/include/lldb/Interpreter/OptionValueProperties.h +++ b/include/lldb/Interpreter/OptionValueProperties.h @@ -1,4 +1,4 @@ -//===-- OptionValueProperties.h --------------------------------------*- C++ -*-===// +//===-- OptionValueProperties.h ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/Core/ConstString.h" @@ -27,10 +29,6 @@ class OptionValueProperties : public std::enable_shared_from_this { public: - - //--------------------------------------------------------------------- - // OptionValueProperties - //--------------------------------------------------------------------- OptionValueProperties () : OptionValue(), m_name (), @@ -42,34 +40,32 @@ public: OptionValueProperties (const ConstString &name); OptionValueProperties (const OptionValueProperties &global_properties); - - virtual - ~OptionValueProperties() - { - } - - virtual Type - GetType () const + + ~OptionValueProperties() override = default; + + Type + GetType() const override { return eTypeProperties; } - virtual bool - Clear (); + bool + Clear() override; - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; - virtual Error - SetValueFromString (llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual void - DumpValue (const ExecutionContext *exe_ctx, - Stream &strm, - uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, + Stream &strm, + uint32_t dump_mask) override; - virtual ConstString - GetName () const + ConstString + GetName() const override { return m_name; } @@ -149,16 +145,16 @@ public: bool value_will_be_modified) const; lldb::OptionValueSP - GetSubValue (const ExecutionContext *exe_ctx, - const char *name, - bool value_will_be_modified, - Error &error) const; + GetSubValue(const ExecutionContext *exe_ctx, + const char *name, + bool value_will_be_modified, + Error &error) const override; - virtual Error - SetSubValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *path, - const char *value); + Error + SetSubValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *path, + const char *value) override; virtual bool PredicateMatches (const ExecutionContext *exe_ctx, @@ -171,6 +167,9 @@ public: OptionValueArch * GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const; + OptionValueLanguage * + GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const; + bool GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const; @@ -251,22 +250,18 @@ public: SetValueChangedCallback (uint32_t property_idx, OptionValueChangedCallback callback, void *baton); -protected: +protected: Property * - ProtectedGetPropertyAtIndex (uint32_t idx) + ProtectedGetPropertyAtIndex(uint32_t idx) { - if (idx < m_properties.size()) - return &m_properties[idx]; - return NULL; + return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr); } const Property * - ProtectedGetPropertyAtIndex (uint32_t idx) const + ProtectedGetPropertyAtIndex(uint32_t idx) const { - if (idx < m_properties.size()) - return &m_properties[idx]; - return NULL; + return ((idx < m_properties.size()) ? &m_properties[idx] : nullptr); } typedef UniqueCStringMap NameToIndex; @@ -278,4 +273,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueProperties_h_ +#endif // liblldb_OptionValueProperties_h_ diff --git a/include/lldb/Interpreter/OptionValueRegex.h b/include/lldb/Interpreter/OptionValueRegex.h index 5e04218dbfdf..a094a402b1a9 100644 --- a/include/lldb/Interpreter/OptionValueRegex.h +++ b/include/lldb/Interpreter/OptionValueRegex.h @@ -12,8 +12,6 @@ // C Includes // C++ Includes -#include - // Other libraries and framework includes // Project includes #include "lldb/Core/RegularExpression.h" @@ -24,44 +22,41 @@ namespace lldb_private { class OptionValueRegex : public OptionValue { public: - OptionValueRegex (const char *value = NULL) : + OptionValueRegex(const char *value = nullptr) : OptionValue(), m_regex (value) { } - virtual - ~OptionValueRegex() - { - } - + ~OptionValueRegex() override = default; + //--------------------------------------------------------------------- // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeRegex; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_regex.Clear(); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -69,9 +64,7 @@ public: const RegularExpression * GetCurrentValue() const { - if (m_regex.IsValid()) - return &m_regex; - return NULL; + return (m_regex.IsValid() ? &m_regex : nullptr); } void @@ -95,4 +88,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueRegex_h_ +#endif // liblldb_OptionValueRegex_h_ diff --git a/include/lldb/Interpreter/OptionValueSInt64.h b/include/lldb/Interpreter/OptionValueSInt64.h index 36ae97ccfcf8..8c8b201b6e82 100644 --- a/include/lldb/Interpreter/OptionValueSInt64.h +++ b/include/lldb/Interpreter/OptionValueSInt64.h @@ -58,8 +58,7 @@ public: { } - virtual - ~OptionValueSInt64() + ~OptionValueSInt64() override { } @@ -67,29 +66,29 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeSInt64; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -169,4 +168,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueSInt64_h_ +#endif // liblldb_OptionValueSInt64_h_ diff --git a/include/lldb/Interpreter/OptionValueString.h b/include/lldb/Interpreter/OptionValueString.h index c75745d402be..bbdd0c8ba55c 100644 --- a/include/lldb/Interpreter/OptionValueString.h +++ b/include/lldb/Interpreter/OptionValueString.h @@ -1,4 +1,4 @@ -//===-- OptionValueString.h --------------------------------------*- C++ -*-===// +//===-- OptionValueString.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -24,7 +24,6 @@ namespace lldb_private { class OptionValueString : public OptionValue { public: - typedef Error (*ValidatorCallback) (const char* string, void* baton); @@ -43,8 +42,8 @@ public: { } - OptionValueString (ValidatorCallback validator, - void* baton = NULL) : + OptionValueString(ValidatorCallback validator, + void* baton = nullptr) : OptionValue(), m_current_value (), m_default_value (), @@ -84,9 +83,9 @@ public: m_default_value.assign (default_value); } - OptionValueString (const char *value, - ValidatorCallback validator, - void* baton = NULL) : + OptionValueString(const char *value, + ValidatorCallback validator, + void* baton = nullptr) : OptionValue(), m_current_value (), m_default_value (), @@ -101,10 +100,10 @@ public: } } - OptionValueString (const char *current_value, - const char *default_value, - ValidatorCallback validator, - void* baton = NULL) : + OptionValueString(const char *current_value, + const char *default_value, + ValidatorCallback validator, + void* baton = nullptr) : OptionValue(), m_current_value (), m_default_value (), @@ -118,38 +117,35 @@ public: m_default_value.assign (default_value); } - virtual - ~OptionValueString() - { - } - + ~OptionValueString() override = default; + //--------------------------------------------------------------------- // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeString; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -213,7 +209,6 @@ public: return m_default_value.empty(); } - protected: std::string m_current_value; std::string m_default_value; @@ -224,4 +219,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueString_h_ +#endif // liblldb_OptionValueString_h_ diff --git a/include/lldb/Interpreter/OptionValueUInt64.h b/include/lldb/Interpreter/OptionValueUInt64.h index 51ff8818dcff..874e8ca16665 100644 --- a/include/lldb/Interpreter/OptionValueUInt64.h +++ b/include/lldb/Interpreter/OptionValueUInt64.h @@ -43,8 +43,7 @@ public: { } - virtual - ~OptionValueUInt64() + ~OptionValueUInt64() override { } @@ -60,29 +59,29 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeUInt64; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_current_value = m_default_value; m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -131,4 +130,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueUInt64_h_ +#endif // liblldb_OptionValueUInt64_h_ diff --git a/include/lldb/Interpreter/OptionValueUUID.h b/include/lldb/Interpreter/OptionValueUUID.h index c6ab48a627f6..4aecc39bc8c4 100644 --- a/include/lldb/Interpreter/OptionValueUUID.h +++ b/include/lldb/Interpreter/OptionValueUUID.h @@ -34,8 +34,7 @@ public: { } - virtual - ~OptionValueUUID() + ~OptionValueUUID() override { } @@ -43,29 +42,29 @@ public: // Virtual subclass pure virtual overrides //--------------------------------------------------------------------- - virtual OptionValue::Type - GetType () const + OptionValue::Type + GetType() const override { return eTypeUUID; } - virtual void - DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + void + DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; - virtual Error - SetValueFromString (llvm::StringRef value, - VarSetOperationType op = eVarSetOperationAssign); + Error + SetValueFromString(llvm::StringRef value, + VarSetOperationType op = eVarSetOperationAssign) override; - virtual bool - Clear () + bool + Clear() override { m_uuid.Clear(); m_value_was_set = false; return true; } - virtual lldb::OptionValueSP - DeepCopy () const; + lldb::OptionValueSP + DeepCopy() const override; //--------------------------------------------------------------------- // Subclass specific functions @@ -89,13 +88,13 @@ public: m_uuid = value; } - virtual size_t - AutoComplete (CommandInterpreter &interpreter, - const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + size_t + AutoComplete(CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; protected: UUID m_uuid; @@ -103,4 +102,4 @@ protected: } // namespace lldb_private -#endif // liblldb_OptionValueUUID_h_ +#endif // liblldb_OptionValueUUID_h_ diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h index 6ecf08d28e75..bac26308a8d1 100644 --- a/include/lldb/Interpreter/Options.h +++ b/include/lldb/Interpreter/Options.h @@ -11,7 +11,6 @@ #define liblldb_Options_h_ // C Includes - // C++ Includes #include #include @@ -32,7 +31,6 @@ namespace lldb_private { return isprint(ch); } - //---------------------------------------------------------------------- /// @class Options Options.h "lldb/Interpreter/Options.h" /// @brief A command line option parsing protocol class. @@ -72,7 +70,7 @@ namespace lldb_private { /// case 'g': debug = true; break; /// case 'v': verbose = true; break; /// case 'l': log_file = option_arg; break; -/// case 'f': log_flags = strtoull(option_arg, NULL, 0); break; +/// case 'f': log_flags = strtoull(option_arg, nullptr, 0); break; /// default: /// error.SetErrorStringWithFormat("unrecognized short option %c", option_val); /// break; @@ -95,11 +93,11 @@ namespace lldb_private { /// /// struct option CommandOptions::g_options[] = /// { -/// { "debug", no_argument, NULL, 'g' }, -/// { "log-file", required_argument, NULL, 'l' }, -/// { "log-flags", required_argument, NULL, 'f' }, -/// { "verbose", no_argument, NULL, 'v' }, -/// { NULL, 0, NULL, 0 } +/// { "debug", no_argument, nullptr, 'g' }, +/// { "log-file", required_argument, nullptr, 'l' }, +/// { "log-flags", required_argument, nullptr, 'f' }, +/// { "verbose", no_argument, nullptr, 'v' }, +/// { nullptr, 0, nullptr, 0 } /// }; /// /// int main (int argc, const char **argv, const char **envp) @@ -119,7 +117,6 @@ namespace lldb_private { class Options { public: - Options (CommandInterpreter &interpreter); virtual @@ -153,7 +150,6 @@ public: // Verify that the options given are in the options table and can // be used together, but there may be some required options that are // missing (used to verify options that get folded into command aliases). - bool VerifyPartialOptions (CommandReturnObject &result); @@ -173,7 +169,10 @@ public: // class that inherits from this class. virtual const OptionDefinition* - GetDefinitions () { return NULL; } + GetDefinitions() + { + return nullptr; + } // Call this prior to parsing any options. This call will call the // subclass OptionParsingStarting() and will avoid the need for all @@ -195,7 +194,7 @@ public: /// /// @param[in] option_arg /// The argument value for the option that the user entered, or - /// NULL if there is no argument for the current option. + /// nullptr if there is no argument for the current option. /// /// /// @see Args::ParseOptions (Options&) @@ -359,15 +358,11 @@ protected: class OptionGroup { public: - OptionGroup () - { - } - + OptionGroup() = default; + virtual - ~OptionGroup () - { - } - + ~OptionGroup() = default; + virtual uint32_t GetNumDefinitions () = 0; @@ -395,7 +390,6 @@ protected: class OptionGroupOptions : public Options { public: - OptionGroupOptions (CommandInterpreter &interpreter) : Options (interpreter), m_option_defs (), @@ -404,12 +398,8 @@ protected: { } - virtual - ~OptionGroupOptions () - { - } - - + ~OptionGroupOptions() override = default; + //---------------------------------------------------------------------- /// Append options from a OptionGroup class. /// @@ -459,18 +449,18 @@ protected: return m_did_finalize; } - virtual Error - SetOptionValue (uint32_t option_idx, - const char *option_arg); + Error + SetOptionValue(uint32_t option_idx, + const char *option_arg) override; - virtual void - OptionParsingStarting (); + void + OptionParsingStarting() override; - virtual Error - OptionParsingFinished (); + Error + OptionParsingFinished() override; const OptionDefinition* - GetDefinitions () + GetDefinitions() override { assert (m_did_finalize); return &m_option_defs[0]; @@ -495,8 +485,7 @@ protected: OptionInfos m_option_infos; bool m_did_finalize; }; - } // namespace lldb_private -#endif // liblldb_Options_h_ +#endif // liblldb_Options_h_ diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h deleted file mode 100644 index df281b533cba..000000000000 --- a/include/lldb/Interpreter/PythonDataObjects.h +++ /dev/null @@ -1,280 +0,0 @@ -//===-- PythonDataObjects.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_PythonDataObjects_h_ -#define liblldb_PythonDataObjects_h_ - -// C Includes -// C++ Includes - -// Other libraries and framework includes -// Project includes -#include "lldb/lldb-defines.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/StructuredData.h" -#include "lldb/Core/Flags.h" -#include "lldb/Interpreter/OptionValue.h" -#include "lldb/lldb-python.h" - -namespace lldb_private { -class PythonString; -class PythonList; -class PythonDictionary; -class PythonObject; -class PythonInteger; - -class StructuredPythonObject : public StructuredData::Generic -{ - public: - StructuredPythonObject() - : StructuredData::Generic() - { - } - - StructuredPythonObject(void *obj) - : StructuredData::Generic(obj) - { - Py_XINCREF(GetValue()); - } - - virtual ~StructuredPythonObject() - { - if (Py_IsInitialized()) - Py_XDECREF(GetValue()); - SetValue(nullptr); - } - - bool - IsValid() const override - { - return GetValue() && GetValue() != Py_None; - } - - void Dump(Stream &s) const override; - - private: - DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); -}; - -enum class PyObjectType -{ - Unknown, - None, - Integer, - Dictionary, - List, - String -}; - - class PythonObject - { - public: - PythonObject () : - m_py_obj(NULL) - { - } - - explicit PythonObject (PyObject* py_obj) : - m_py_obj(NULL) - { - Reset (py_obj); - } - - PythonObject (const PythonObject &rhs) : - m_py_obj(NULL) - { - Reset (rhs.m_py_obj); - } - - virtual - ~PythonObject () - { - Reset (NULL); - } - - bool - Reset (const PythonObject &object) - { - return Reset(object.get()); - } - - virtual bool - Reset (PyObject* py_obj = NULL) - { - if (py_obj != m_py_obj) - { - if (Py_IsInitialized()) - Py_XDECREF(m_py_obj); - m_py_obj = py_obj; - if (Py_IsInitialized()) - Py_XINCREF(m_py_obj); - } - return true; - } - - void - Dump () const - { - if (m_py_obj) - _PyObject_Dump (m_py_obj); - else - puts ("NULL"); - } - - void - Dump (Stream &strm) const; - - PyObject* - get () const - { - return m_py_obj; - } - - PyObjectType GetObjectType() const; - - PythonString - Repr (); - - PythonString - Str (); - - explicit operator bool () const - { - return m_py_obj != NULL; - } - - bool - IsNULLOrNone () const; - - StructuredData::ObjectSP CreateStructuredObject() const; - - protected: - PyObject* m_py_obj; - }; - - class PythonString: public PythonObject - { - public: - PythonString (); - PythonString (PyObject *o); - PythonString (const PythonObject &object); - PythonString (llvm::StringRef string); - PythonString (const char *string); - virtual ~PythonString (); - - virtual bool - Reset (PyObject* py_obj = NULL); - - llvm::StringRef - GetString() const; - - size_t - GetSize() const; - - void SetString(llvm::StringRef string); - - StructuredData::StringSP CreateStructuredString() const; - }; - - class PythonInteger: public PythonObject - { - public: - - PythonInteger (); - PythonInteger (PyObject* py_obj); - PythonInteger (const PythonObject &object); - PythonInteger (int64_t value); - virtual ~PythonInteger (); - - virtual bool - Reset (PyObject* py_obj = NULL); - - int64_t GetInteger() const; - - void - SetInteger (int64_t value); - - StructuredData::IntegerSP CreateStructuredInteger() const; - }; - - class PythonList: public PythonObject - { - public: - - PythonList (bool create_empty); - PythonList (PyObject* py_obj); - PythonList (const PythonObject &object); - PythonList (uint32_t count); - virtual ~PythonList (); - - virtual bool - Reset (PyObject* py_obj = NULL); - - uint32_t GetSize() const; - - PythonObject GetItemAtIndex(uint32_t index) const; - - void - SetItemAtIndex (uint32_t index, const PythonObject &object); - - void - AppendItem (const PythonObject &object); - - StructuredData::ArraySP CreateStructuredArray() const; - }; - - class PythonDictionary: public PythonObject - { - public: - - explicit PythonDictionary (bool create_empty); - PythonDictionary (PyObject* object); - PythonDictionary (const PythonObject &object); - virtual ~PythonDictionary (); - - virtual bool - Reset (PyObject* object = NULL); - - uint32_t GetSize() const; - - PythonObject - GetItemForKey (const PythonString &key) const; - - const char * - GetItemForKeyAsString (const PythonString &key, const char *fail_value = NULL) const; - - int64_t - GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value = 0) const; - - PythonObject - GetItemForKey (const char *key) const; - - typedef bool (*DictionaryIteratorCallback)(PythonString* key, PythonDictionary* dict); - - PythonList - GetKeys () const; - - PythonString - GetKeyAtPosition (uint32_t pos) const; - - PythonObject - GetValueAtPosition (uint32_t pos) const; - - void - SetItemForKey (const PythonString &key, PyObject *value); - - void - SetItemForKey (const PythonString &key, const PythonObject& value); - - StructuredData::DictionarySP CreateStructuredDictionary() const; - }; - -} // namespace lldb_private - -#endif // liblldb_PythonDataObjects_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h index 0f45dd8245e9..eafc03a00cca 100644 --- a/include/lldb/Interpreter/ScriptInterpreter.h +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -10,37 +10,36 @@ #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/Core/Broadcaster.h" #include "lldb/Core/Error.h" +#include "lldb/Core/PluginInterface.h" #include "lldb/Core/StructuredData.h" #include "lldb/Utility/PseudoTerminal.h" - namespace lldb_private { class ScriptInterpreterLocker { public: - ScriptInterpreterLocker () - { - } + ScriptInterpreterLocker() = default; - virtual ~ScriptInterpreterLocker () - { - } + virtual ~ScriptInterpreterLocker() = default; + private: DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterLocker); }; - -class ScriptInterpreter +class ScriptInterpreter : public PluginInterface { public: - typedef enum { eScriptReturnTypeCharPtr, @@ -62,7 +61,7 @@ public: ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang); - virtual ~ScriptInterpreter (); + ~ScriptInterpreter() override; struct ExecuteScriptOptions { @@ -174,13 +173,13 @@ public: } virtual bool - GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL) + GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr) { return false; } virtual bool - GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL) + GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr) { return false; } @@ -192,13 +191,13 @@ public: } virtual bool - GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL) + GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr) { return false; } virtual bool - GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL) + GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr) { return false; } @@ -324,7 +323,6 @@ public: SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, const char *function_name) { - return; } /// Set a one-liner as the callback for the watchpoint. @@ -332,7 +330,6 @@ public: SetWatchpointCommandCallback (WatchpointOptions *wp_options, const char *oneliner) { - return; } virtual bool @@ -349,7 +346,7 @@ public: } virtual size_t - CalculateNumChildren(const StructuredData::ObjectSP &implementor) + CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) { return 0; } @@ -459,7 +456,7 @@ public: virtual bool GetDocumentationForItem (const char* item, std::string& dest) { - dest.clear(); + dest.clear(); return false; } @@ -514,8 +511,8 @@ public: int GetMasterFileDescriptor (); - CommandInterpreter & - GetCommandInterpreter (); + CommandInterpreter & + GetCommandInterpreter(); static std::string LanguageToString (lldb::ScriptLanguage language); @@ -530,4 +527,4 @@ protected: } // namespace lldb_private -#endif // #ifndef liblldb_ScriptInterpreter_h_ +#endif // liblldb_ScriptInterpreter_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreterNone.h b/include/lldb/Interpreter/ScriptInterpreterNone.h deleted file mode 100644 index 6c82b60b0bcd..000000000000 --- a/include/lldb/Interpreter/ScriptInterpreterNone.h +++ /dev/null @@ -1,35 +0,0 @@ -//===-- ScriptInterpreterNone.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_ScriptInterpreterNone_h_ -#define liblldb_ScriptInterpreterNone_h_ - -#include "lldb/Interpreter/ScriptInterpreter.h" - -namespace lldb_private { - -class ScriptInterpreterNone : public ScriptInterpreter -{ -public: - - ScriptInterpreterNone (CommandInterpreter &interpreter); - - ~ScriptInterpreterNone (); - - bool - ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options = ExecuteScriptOptions()); - - void - ExecuteInterpreterLoop (); - -}; - -} // namespace lldb_private - -#endif // #ifndef liblldb_ScriptInterpreterNone_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h deleted file mode 100644 index 058058ecccb5..000000000000 --- a/include/lldb/Interpreter/ScriptInterpreterPython.h +++ /dev/null @@ -1,563 +0,0 @@ -//===-- ScriptInterpreterPython.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_ScriptInterpreterPython_h_ -#define liblldb_ScriptInterpreterPython_h_ - -#ifdef LLDB_DISABLE_PYTHON - -// Python is disabled in this build - -#else - -#include "lldb/lldb-python.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/IOHandler.h" -#include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Interpreter/PythonDataObjects.h" -#include "lldb/Host/Terminal.h" - -class IOHandlerPythonInterpreter; - -namespace lldb_private { - -class ScriptInterpreterPython : - public ScriptInterpreter, - public IOHandlerDelegateMultiline -{ -public: - typedef void (*SWIGInitCallback) (void); - - typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::BreakpointLocationSP &bp_loc_sp); - - typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::WatchpointSP &wp_sp); - - typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, - void *session_dictionary, - const lldb::ValueObjectSP& valobj_sp, - void** pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP& options, - std::string& retval); - - typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP& valobj_sp); - - typedef void* (*SWIGPythonCreateCommandObject) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::DebuggerSP debugger_sp); - - typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ThreadPlanSP& thread_plan_sp); - - typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error); - - typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP& process_sp); - - typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor); - typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); - typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); - typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); - typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data); - typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); - typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); - typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor); - - typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - - typedef bool (*SWIGPythonCallCommandObject) (void *implementor, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - - - typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger); - - typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ProcessSP& process, - std::string& output); - typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ThreadSP& thread, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name, - const char* session_dictionary_name, - lldb::TargetSP& target, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name, - const char* session_dictionary_name, - lldb::StackFrameSP& frame, - std::string& output); - - typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name, - const char* session_dictionary_name, - lldb::ValueObjectSP& value, - std::string& output); - - typedef void* (*SWIGPython_GetDynamicSetting) (void* module, - const char* setting, - const lldb::TargetSP& target_sp); - - friend class ::IOHandlerPythonInterpreter; - - ScriptInterpreterPython (CommandInterpreter &interpreter); - - ~ScriptInterpreterPython (); - - bool - Interrupt() override; - - bool - ExecuteOneLine (const char *command, - CommandReturnObject *result, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - void - ExecuteInterpreterLoop () override; - - bool - ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ScriptReturnType return_type, - void *ret_value, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - lldb_private::Error - ExecuteMultipleLines (const char *in_string, - const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; - - Error - ExportFunctionDefinitionToInterpreter (StringList &function_def) override; - - bool - GenerateTypeScriptFunction (StringList &input, std::string& output, const void* name_token = NULL) override; - - bool - GenerateTypeSynthClass (StringList &input, std::string& output, const void* name_token = NULL) override; - - bool - GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token = NULL) override; - - // use this if the function code is just a one-liner script - bool - GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token = NULL) override; - - bool - GenerateScriptAliasFunction (StringList &input, std::string& output) override; - - StructuredData::ObjectSP CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override; - - StructuredData::GenericSP CreateScriptCommandObject (const char *class_name) override; - - StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override; - - bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; - bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; - lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override; - - StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override; - - StructuredData::DictionarySP OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::ArraySP OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; - - StructuredData::StringSP OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) override; - - StructuredData::DictionarySP OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, - lldb::addr_t context) override; - - StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) override; - - StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, - lldb_private::Error &error) override; - - size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor) override; - - lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override; - - int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) override; - - bool UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; - - bool MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; - - lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; - - bool - RunScriptBasedCommand(const char* impl_function, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) override; - - bool - RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) override; - - Error - GenerateFunction(const char *signature, const StringList &input) override; - - Error - GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) override; - - bool - GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) override; - -// static size_t -// GenerateBreakpointOptionsCommandCallback (void *baton, -// InputReader &reader, -// lldb::InputReaderAction notification, -// const char *bytes, -// size_t bytes_len); -// -// static size_t -// GenerateWatchpointOptionsCommandCallback (void *baton, -// InputReader &reader, -// lldb::InputReaderAction notification, -// const char *bytes, -// size_t bytes_len); - - static bool - BreakpointCallbackFunction (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - static bool - WatchpointCallbackFunction (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t watch_id); - - bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, - const TypeSummaryOptions &options, std::string &retval) override; - - void - Clear () override; - - bool - GetDocumentationForItem (const char* item, std::string& dest) override; - - bool - GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; - - uint32_t - GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) override; - - bool - GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; - - bool - CheckObjectExists (const char* name) override - { - if (!name || !name[0]) - return false; - std::string temp; - return GetDocumentationForItem (name,temp); - } - - bool - RunScriptFormatKeyword (const char* impl_function, - Process* process, - std::string& output, - Error& error) override; - - bool - RunScriptFormatKeyword (const char* impl_function, - Thread* thread, - std::string& output, - Error& error) override; - - bool - RunScriptFormatKeyword (const char* impl_function, - Target* target, - std::string& output, - Error& error) override; - - bool - RunScriptFormatKeyword (const char* impl_function, - StackFrame* frame, - std::string& output, - Error& error) override; - - bool - RunScriptFormatKeyword (const char* impl_function, - ValueObject* value, - std::string& output, - Error& error) override; - - bool LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error, - StructuredData::ObjectSP *module_sp = nullptr) override; - - bool - IsReservedWord (const char* word) override; - - std::unique_ptr - AcquireInterpreterLock () override; - - void - CollectDataForBreakpointCommandCallback (std::vector &bp_options_vec, - CommandReturnObject &result) override; - - void - CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result) override; - - /// Set the callback body text into the callback for the breakpoint. - Error - SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *callback_body) override; - - void - SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, - const char *function_name) override; - - /// Set a one-liner as the callback for the watchpoint. - void - SetWatchpointCommandCallback (WatchpointOptions *wp_options, - const char *oneliner) override; - - StringList - ReadCommandInputFromUser (FILE *in_file); - - void ResetOutputFileHandle(FILE *new_fh) override; - - static void - InitializePrivate (); - - static void - InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction swig_breakpoint_callback, - SWIGWatchpointCallbackFunction swig_watchpoint_callback, - SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, - SWIGPythonCreateSyntheticProvider swig_synthetic_script, - SWIGPythonCreateCommandObject swig_create_cmd, - SWIGPythonCalculateNumChildren swig_calc_children, - SWIGPythonGetChildAtIndex swig_get_child_index, - SWIGPythonGetIndexOfChildWithName swig_get_index_child, - SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , - SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, - SWIGPythonUpdateSynthProviderInstance swig_update_provider, - SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, - SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, - SWIGPythonCallCommand swig_call_command, - SWIGPythonCallCommandObject swig_call_command_object, - SWIGPythonCallModuleInit swig_call_module_init, - SWIGPythonCreateOSPlugin swig_create_os_plugin, - SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, - SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, - SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, - SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, - SWIGPython_GetDynamicSetting swig_plugin_get, - SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, - SWIGPythonCallThreadPlan swig_call_thread_plan); - - const char * - GetDictionaryName () - { - return m_dictionary_name.c_str(); - } - - - PyThreadState * - GetThreadState() - { - return m_command_thread_state; - } - - void - SetThreadState (PyThreadState *s) - { - if (s) - m_command_thread_state = s; - } - - //---------------------------------------------------------------------- - // IOHandlerDelegate - //---------------------------------------------------------------------- - void - IOHandlerActivated (IOHandler &io_handler) override; - - void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override; - -protected: - - bool - EnterSession (uint16_t on_entry_flags, - FILE *in, - FILE *out, - FILE *err); - - void - LeaveSession (); - - void - SaveTerminalState (int fd); - - void - RestoreTerminalState (); - - class SynchronicityHandler - { - private: - lldb::DebuggerSP m_debugger_sp; - ScriptedCommandSynchronicity m_synch_wanted; - bool m_old_asynch; - public: - SynchronicityHandler(lldb::DebuggerSP, - ScriptedCommandSynchronicity); - ~SynchronicityHandler(); - }; - -public: - class Locker : public ScriptInterpreterLocker - { - public: - - enum OnEntry - { - AcquireLock = 0x0001, - InitSession = 0x0002, - InitGlobals = 0x0004, - NoSTDIN = 0x0008 - }; - - enum OnLeave - { - FreeLock = 0x0001, - FreeAcquiredLock = 0x0002, // do not free the lock if we already held it when calling constructor - TearDownSession = 0x0004 - }; - - Locker (ScriptInterpreterPython *py_interpreter = NULL, - uint16_t on_entry = AcquireLock | InitSession, - uint16_t on_leave = FreeLock | TearDownSession, - FILE *in = NULL, - FILE *out = NULL, - FILE *err = NULL); - - ~Locker (); - - private: - - bool - DoAcquireLock (); - - bool - DoInitSession (uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); - - bool - DoFreeLock (); - - bool - DoTearDownSession (); - - static void - ReleasePythonLock (); - - bool m_teardown_session; - ScriptInterpreterPython *m_python_interpreter; -// FILE* m_tmp_fh; - PyGILState_STATE m_GILState; - }; -protected: - enum class AddLocation - { - Beginning, - End - }; - - static void AddToSysPath(AddLocation location, std::string path); - - uint32_t - IsExecutingPython () const - { - return m_lock_count > 0; - } - - uint32_t - IncrementLockCount() - { - return ++m_lock_count; - } - - uint32_t - DecrementLockCount() - { - if (m_lock_count > 0) - --m_lock_count; - return m_lock_count; - } - - enum ActiveIOHandler { - eIOHandlerNone, - eIOHandlerBreakpoint, - eIOHandlerWatchpoint - }; - PythonObject & - GetMainModule (); - - PythonDictionary & - GetSessionDictionary (); - - PythonDictionary & - GetSysModuleDictionary (); - - bool - GetEmbeddedInterpreterModuleObjects (); - - PythonObject m_saved_stdin; - PythonObject m_saved_stdout; - PythonObject m_saved_stderr; - PythonObject m_main_module; - PythonObject m_lldb_module; - PythonDictionary m_session_dict; - PythonDictionary m_sys_module_dict; - PythonObject m_run_one_line_function; - PythonObject m_run_one_line_str_global; - std::string m_dictionary_name; - TerminalState m_terminal_state; - ActiveIOHandler m_active_io_handler; - bool m_session_is_active; - bool m_pty_slave_is_open; - bool m_valid_session; - uint32_t m_lock_count; - PyThreadState *m_command_thread_state; -}; -} // namespace lldb_private - -#endif // #ifdef LLDB_DISABLE_PYTHON - -#endif // #ifndef liblldb_ScriptInterpreterPython_h_ diff --git a/include/lldb/Symbol/ArmUnwindInfo.h b/include/lldb/Symbol/ArmUnwindInfo.h new file mode 100644 index 000000000000..b19af23744a4 --- /dev/null +++ b/include/lldb/Symbol/ArmUnwindInfo.h @@ -0,0 +1,77 @@ +//===-- ArmUnwindInfo.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_ArmUnwindInfo_h_ +#define liblldb_ArmUnwindInfo_h_ + +#include + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/lldb-private.h" + +/* + * Unwind information reader and parser for the ARM exception handling ABI + * + * Implemented based on: + * Exception Handling ABI for the ARM Architecture + * Document number: ARM IHI 0038A (current through ABI r2.09) + * Date of Issue: 25th January 2007, reissued 30th November 2012 + * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf + */ + +namespace lldb_private { + +class ArmUnwindInfo +{ +public: + ArmUnwindInfo(const ObjectFile& objfile, + lldb::SectionSP& arm_exidx, + lldb::SectionSP& arm_extab); + + ~ArmUnwindInfo(); + + bool + GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan); + +private: + struct ArmExidxEntry + { + ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d); + + bool + operator<(const ArmExidxEntry& other) const; + + uint32_t file_address; + lldb::addr_t address; + uint32_t data; + }; + + const uint8_t* + GetExceptionHandlingTableEntry(const Address& addr); + + uint8_t + GetByteAtOffset(const uint32_t* data, uint16_t offset) const; + + uint64_t + GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const; + + const lldb::ByteOrder m_byte_order; + lldb::SectionSP m_arm_exidx_sp; // .ARM.exidx section + lldb::SectionSP m_arm_extab_sp; // .ARM.extab section + DataExtractor m_arm_exidx_data; // .ARM.exidx section data + DataExtractor m_arm_extab_data; // .ARM.extab section data + std::vector m_exidx_entries; +}; + +} // namespace lldb_private + +#endif // liblldb_ArmUnwindInfo_h_ diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h index 59671b00b3b8..6c0793dda80f 100644 --- a/include/lldb/Symbol/Block.h +++ b/include/lldb/Symbol/Block.h @@ -10,6 +10,12 @@ #ifndef liblldb_Block_h_ #define liblldb_Block_h_ +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/RangeMap.h" @@ -17,7 +23,7 @@ #include "lldb/Core/UserID.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" namespace lldb_private { @@ -76,7 +82,7 @@ public: //------------------------------------------------------------------ /// Destructor. //------------------------------------------------------------------ - virtual ~Block (); + ~Block() override; //------------------------------------------------------------------ /// Add a child to this object. @@ -110,20 +116,20 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - CalculateSymbolContext(SymbolContext* sc); + void + CalculateSymbolContext(SymbolContext* sc) override; - virtual lldb::ModuleSP - CalculateSymbolContextModule (); + lldb::ModuleSP + CalculateSymbolContextModule() override; - virtual CompileUnit * - CalculateSymbolContextCompileUnit (); + CompileUnit * + CalculateSymbolContextCompileUnit() override; - virtual Function * - CalculateSymbolContextFunction (); + Function * + CalculateSymbolContextFunction() override; - virtual Block * - CalculateSymbolContextBlock (); + Block * + CalculateSymbolContextBlock() override; //------------------------------------------------------------------ /// Check if an offset is in one of the block offset ranges. @@ -192,8 +198,8 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - DumpSymbolContext(Stream *s); + void + DumpSymbolContext(Stream *s) override; void DumpAddressRanges (Stream *s, @@ -209,20 +215,19 @@ public: /// Get the parent block. /// /// @return - /// The parent block pointer, or NULL if this block has no + /// The parent block pointer, or nullptr if this block has no /// parent. //------------------------------------------------------------------ Block * GetParent () const; - //------------------------------------------------------------------ /// Get the inlined block that contains this block. /// /// @return /// If this block contains inlined function info, it will return /// this block, else parent blocks will be searched to see if - /// any contain this block. NULL will be returned if this block + /// any contain this block. nullptr will be returned if this block /// nor any parent blocks are inlined function blocks. //------------------------------------------------------------------ Block * @@ -232,7 +237,7 @@ public: /// Get the inlined parent block for this block. /// /// @return - /// The parent block pointer, or NULL if this block has no + /// The parent block pointer, or nullptr if this block has no /// parent. //------------------------------------------------------------------ Block * @@ -242,7 +247,7 @@ public: /// Get the sibling block for this block. /// /// @return - /// The sibling block pointer, or NULL if this block has no + /// The sibling block pointer, or nullptr if this block has no /// sibling. //------------------------------------------------------------------ Block * @@ -252,15 +257,13 @@ public: /// Get the first child block. /// /// @return - /// The first child block pointer, or NULL if this block has no + /// The first child block pointer, or nullptr if this block has no /// children. //------------------------------------------------------------------ Block * GetFirstChild () const { - if (m_children.empty()) - return NULL; - return m_children.front().get(); + return (m_children.empty() ? nullptr : m_children.front().get()); } //------------------------------------------------------------------ @@ -278,7 +281,6 @@ public: lldb::VariableListSP GetBlockVariableList (bool can_create); - //------------------------------------------------------------------ /// Get the variable list for this block and optionally all child /// blocks if \a get_child_variables is \b true. @@ -330,7 +332,7 @@ public: /// added to the variable list until there are no parent blocks /// or the parent block has inlined function info. /// - /// @param[in/out] variable_list + /// @param[in,out] variable_list /// All variables in this block, and optionally all parent /// blocks will be added to this list. /// @@ -348,7 +350,7 @@ public: /// Get const accessor for any inlined function information. /// /// @return - /// A const pointer to any inlined function information, or NULL + /// A const pointer to any inlined function information, or nullptr /// if this is a regular block. //------------------------------------------------------------------ const InlineFunctionInfo* @@ -357,8 +359,8 @@ public: return m_inlineInfoSP.get(); } - clang::DeclContext * - GetClangDeclContext(); + CompilerDeclContext + GetDeclContext(); //------------------------------------------------------------------ /// Get the memory cost of this object. @@ -377,16 +379,16 @@ public: /// /// @param[in] name /// The method name for the inlined function. This value should - /// not be NULL. + /// not be nullptr. /// /// @param[in] mangled /// The mangled method name for the inlined function. This can - /// be NULL if there is no mangled name for an inlined function + /// be nullptr if there is no mangled name for an inlined function /// or if the name is the same as \a name. /// /// @param[in] decl_ptr /// A optional pointer to declaration information for the - /// inlined function information. This value can be NULL to + /// inlined function information. This value can be nullptr to /// indicate that no declaration information is available. /// /// @param[in] call_decl_ptr @@ -399,7 +401,6 @@ public: const Declaration *decl_ptr, const Declaration *call_decl_ptr); - void SetParentScope (SymbolContextScope *parent_scope) { @@ -422,8 +423,6 @@ public: m_variable_list_sp = variable_list_sp; } - - bool BlockInfoHasBeenParsed() const { @@ -491,7 +490,6 @@ private: DISALLOW_COPY_AND_ASSIGN (Block); }; - } // namespace lldb_private -#endif // liblldb_Block_h_ +#endif // liblldb_Block_h_ diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h index a411e42fe0c5..0314ce060e38 100644 --- a/include/lldb/Symbol/ClangASTContext.h +++ b/include/lldb/Symbol/ClangASTContext.h @@ -14,7 +14,11 @@ #include // C++ Includes +#include #include +#include +#include +#include #include #include #include @@ -24,36 +28,71 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/TemplateBase.h" - // Project includes +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/TypeSystem.h" namespace lldb_private { class Declaration; -class ClangASTContext +class ClangASTContext : public TypeSystem { public: typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); - + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const TypeSystem *ts) + { + return ts->getKind() == TypeSystem::eKindClang; + } + //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - ClangASTContext (const char *triple = NULL); + ClangASTContext(const char *triple = nullptr); + + ~ClangASTContext() override; + + //------------------------------------------------------------------ + // PluginInterface functions + //------------------------------------------------------------------ + ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + static ConstString + GetPluginNameStatic (); - ~ClangASTContext(); + static lldb::TypeSystemSP + CreateInstance (lldb::LanguageType language, Module *module, Target *target); + static void + EnumerateSupportedLanguages(std::set &languages_for_types, std::set &languages_for_expressions); + + static void + Initialize (); + + static void + Terminate (); + static ClangASTContext* GetASTContext (clang::ASTContext* ast_ctx); clang::ASTContext * getASTContext(); - + + void setASTContext(clang::ASTContext* ast_ctx); + clang::Builtin::Context * getBuiltinContext(); @@ -78,6 +117,9 @@ public: clang::DiagnosticConsumer * getDiagnosticConsumer(); + clang::MangleContext * + getMangleContext(); + std::shared_ptr &getTargetOptions(); clang::TargetInfo * @@ -109,7 +151,16 @@ public: { return ClangASTContext::GetCompleteDecl(getASTContext(), decl); } - + + static void + DumpDeclHiearchy (clang::Decl *decl); + + static void + DumpDeclContextHiearchy (clang::DeclContext *decl_ctx); + + static bool + DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl); + static bool GetCompleteDecl (clang::ASTContext *ast, clang::Decl *decl); @@ -141,47 +192,53 @@ public: //------------------------------------------------------------------ // Basic Types //------------------------------------------------------------------ - ClangASTType + CompilerType GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, - uint32_t bit_size); + size_t bit_size) override; - static ClangASTType + static CompilerType GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast, lldb::Encoding encoding, uint32_t bit_size); - ClangASTType + CompilerType GetBasicType (lldb::BasicType type); - static ClangASTType + static CompilerType GetBasicType (clang::ASTContext *ast, lldb::BasicType type); - static ClangASTType + static CompilerType GetBasicType (clang::ASTContext *ast, const ConstString &name); static lldb::BasicType GetBasicTypeEnumeration (const ConstString &name); - ClangASTType + CompilerType GetBuiltinTypeForDWARFEncodingAndBitSize ( const char *type_name, uint32_t dw_ate, uint32_t bit_size); - ClangASTType + CompilerType GetCStringType(bool is_const); - static ClangASTType + static CompilerType GetUnknownAnyType(clang::ASTContext *ast); - ClangASTType + CompilerType GetUnknownAnyType() { return ClangASTContext::GetUnknownAnyType(getASTContext()); } + static clang::DeclContext * + GetDeclContextForType (clang::QualType type); + + static clang::DeclContext * + GetDeclContextForType (const CompilerType& type); + uint32_t - GetPointerByteSize (); + GetPointerByteSize () override; static clang::DeclContext * GetTranslationUnitDecl (clang::ASTContext *ast); @@ -192,40 +249,30 @@ public: return GetTranslationUnitDecl (getASTContext()); } - static bool - GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx, - lldb::LanguageType &language, - bool &is_instance_method, - ConstString &language_object_name); - - static ClangASTType - CopyType(clang::ASTContext *dest_context, - ClangASTType source_type); - static clang::Decl * CopyDecl (clang::ASTContext *dest_context, clang::ASTContext *source_context, clang::Decl *source_decl); static bool - AreTypesSame(ClangASTType type1, - ClangASTType type2, + AreTypesSame(CompilerType type1, + CompilerType type2, bool ignore_qualifiers = false); - static ClangASTType + static CompilerType GetTypeForDecl (clang::NamedDecl *decl); - static ClangASTType + static CompilerType GetTypeForDecl (clang::TagDecl *decl); - static ClangASTType + static CompilerType GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl); template - ClangASTType + CompilerType GetTypeForIdentifier (const ConstString &type_name) { - ClangASTType clang_type; + CompilerType compiler_type; if (type_name.GetLength()) { @@ -241,17 +288,17 @@ public: { clang::NamedDecl *named_decl = result[0]; if (const RecordDeclType *record_decl = llvm::dyn_cast(named_decl)) - clang_type.SetClangType(ast, clang::QualType(record_decl->getTypeForDecl(), 0)); + compiler_type.SetCompilerType(ast, clang::QualType(record_decl->getTypeForDecl(), 0)); } } } - return clang_type; + return compiler_type; } - ClangASTType + CompilerType GetOrCreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, ClangASTType > >& type_fields, + const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, bool packed = false); //------------------------------------------------------------------ @@ -268,18 +315,13 @@ public: GetNumBaseClasses (const clang::CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes); - static uint32_t - GetIndexForRecordBase (const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes); - - ClangASTType - CreateRecordType (clang::DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *name, - int kind, - lldb::LanguageType language, - ClangASTMetadata *metadata = NULL); + CompilerType + CreateRecordType(clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *name, + int kind, + lldb::LanguageType language, + ClangASTMetadata *metadata = nullptr); class TemplateParameterInfos { @@ -328,7 +370,7 @@ public: int kind, const TemplateParameterInfos &infos); - ClangASTType + CompilerType CreateClassTemplateSpecializationType (clang::ClassTemplateSpecializationDecl *class_template_specialization_decl); static clang::DeclContext * @@ -354,17 +396,24 @@ public: static bool RecordHasFields (const clang::RecordDecl *record_decl); - - ClangASTType - CreateObjCClass (const char *name, - clang::DeclContext *decl_ctx, - bool isForwardDecl, - bool isInternal, - ClangASTMetadata *metadata = NULL); + CompilerType + CreateObjCClass(const char *name, + clang::DeclContext *decl_ctx, + bool isForwardDecl, + bool isInternal, + ClangASTMetadata *metadata = nullptr); + + bool + SetTagTypeKind (clang::QualType type, int kind) const; + + bool + SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl, + int default_accessibility, + int *assigned_accessibilities, + size_t num_assigned_accessibilities); // Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations - //------------------------------------------------------------------ // Namespace Declarations //------------------------------------------------------------------ @@ -380,21 +429,21 @@ public: clang::FunctionDecl * CreateFunctionDeclaration (clang::DeclContext *decl_ctx, const char *name, - const ClangASTType &function_Type, + const CompilerType &function_Type, int storage, bool is_inline); - static ClangASTType + static CompilerType CreateFunctionType (clang::ASTContext *ast, - const ClangASTType &result_type, - const ClangASTType *args, + const CompilerType &result_type, + const CompilerType *args, unsigned num_args, bool is_variadic, unsigned type_quals); - ClangASTType - CreateFunctionType (const ClangASTType &result_type, - const ClangASTType *args, + CompilerType + CreateFunctionType (const CompilerType &result_type, + const CompilerType *args, unsigned num_args, bool is_variadic, unsigned type_quals) @@ -409,7 +458,7 @@ public: clang::ParmVarDecl * CreateParameterDeclaration (const char *name, - const ClangASTType ¶m_type, + const CompilerType ¶m_type, int storage); void @@ -421,57 +470,732 @@ public: // Array Types //------------------------------------------------------------------ - ClangASTType - CreateArrayType (const ClangASTType &element_type, + CompilerType + CreateArrayType (const CompilerType &element_type, size_t element_count, bool is_vector); //------------------------------------------------------------------ // Enumeration Types //------------------------------------------------------------------ - ClangASTType + CompilerType CreateEnumerationType (const char *name, clang::DeclContext *decl_ctx, const Declaration &decl, - const ClangASTType &integer_qual_type); + const CompilerType &integer_qual_type); //------------------------------------------------------------------ // Integer type functions //------------------------------------------------------------------ - - ClangASTType - GetIntTypeFromBitSize (size_t bit_size, bool is_signed) - { - return GetIntTypeFromBitSize (getASTContext(), bit_size, is_signed); - } - - static ClangASTType + + static CompilerType GetIntTypeFromBitSize (clang::ASTContext *ast, size_t bit_size, bool is_signed); - ClangASTType + CompilerType GetPointerSizedIntType (bool is_signed) { return GetPointerSizedIntType (getASTContext(), is_signed); } - static ClangASTType + static CompilerType GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed); //------------------------------------------------------------------ // Floating point functions //------------------------------------------------------------------ + + static CompilerType + GetFloatTypeFromBitSize (clang::ASTContext *ast, + size_t bit_size); + + //------------------------------------------------------------------ + // TypeSystem methods + //------------------------------------------------------------------ + DWARFASTParser * + GetDWARFParser () override; + + //------------------------------------------------------------------ + // ClangASTContext callbacks for external source lookups. + //------------------------------------------------------------------ + static void + CompleteTagDecl (void *baton, clang::TagDecl *); + + static void + CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); + + static bool + LayoutRecordType(void *baton, + const clang::RecordDecl *record_decl, + uint64_t &size, + uint64_t &alignment, + llvm::DenseMap &field_offsets, + llvm::DenseMap &base_offsets, + llvm::DenseMap &vbase_offsets); + + //---------------------------------------------------------------------- + // CompilerDecl override functions + //---------------------------------------------------------------------- + lldb::VariableSP + DeclGetVariable (void *opaque_decl) override; + + void + DeclLinkToObject (void *opaque_decl, std::shared_ptr object) override; - ClangASTType - GetFloatTypeFromBitSize (size_t bit_size) + ConstString + DeclGetName (void *opaque_decl) override; + + ConstString + DeclGetMangledName (void *opaque_decl) override; + + CompilerDeclContext + DeclGetDeclContext (void *opaque_decl) override; + + CompilerType + DeclGetFunctionReturnType(void *opaque_decl) override; + + size_t + DeclGetFunctionNumArguments(void *opaque_decl) override; + + CompilerType + DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx) override; + + //---------------------------------------------------------------------- + // CompilerDeclContext override functions + //---------------------------------------------------------------------- + + std::vector + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name) 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; + + //---------------------------------------------------------------------- + // Clang specific CompilerType predicates + //---------------------------------------------------------------------- + + static bool + IsClangType (const CompilerType &ct) { - return GetFloatTypeFromBitSize (getASTContext(), bit_size); + return llvm::dyn_cast_or_null(ct.GetTypeSystem()) != nullptr && ct.GetOpaqueQualType() != nullptr; } - static ClangASTType - GetFloatTypeFromBitSize (clang::ASTContext *ast, - size_t bit_size); + //---------------------------------------------------------------------- + // Clang specific clang::DeclContext functions + //---------------------------------------------------------------------- + + static clang::DeclContext * + DeclContextGetAsDeclContext (const CompilerDeclContext &dc); + + static clang::ObjCMethodDecl * + DeclContextGetAsObjCMethodDecl (const CompilerDeclContext &dc); + + static clang::CXXMethodDecl * + DeclContextGetAsCXXMethodDecl (const CompilerDeclContext &dc); + + static clang::FunctionDecl * + DeclContextGetAsFunctionDecl (const CompilerDeclContext &dc); + + static clang::NamespaceDecl * + DeclContextGetAsNamespaceDecl (const CompilerDeclContext &dc); + + static ClangASTMetadata * + DeclContextGetMetaData (const CompilerDeclContext &dc, const void *object); + + static clang::ASTContext * + DeclContextGetClangASTContext (const CompilerDeclContext &dc); + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + bool + IsArrayType (lldb::opaque_compiler_type_t type, + CompilerType *element_type, + uint64_t *size, + bool *is_incomplete) override; + + bool + IsVectorType (lldb::opaque_compiler_type_t type, + CompilerType *element_type, + uint64_t *size) override; + + bool + IsAggregateType (lldb::opaque_compiler_type_t type) override; + + bool + IsAnonymousType (lldb::opaque_compiler_type_t type) override; + + bool + IsBeingDefined (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 + IsConst(lldb::opaque_compiler_type_t type) override; + + bool + IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) override; + + static bool + IsCXXClassType (const CompilerType& type); + + 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) override; + + uint32_t + IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr) 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 + IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) override; + + static bool + IsObjCClassType (const CompilerType& type); + + static bool + IsObjCClassTypeAndHasIVars (const CompilerType& type, bool check_superclass); + + static bool + IsObjCObjectOrInterfaceType (const CompilerType& type); + + static bool + IsObjCObjectPointerType(const CompilerType& type, CompilerType *target_type = nullptr); + + bool + IsPolymorphicClass (lldb::opaque_compiler_type_t type) override; + + bool + IsPossibleDynamicType(lldb::opaque_compiler_type_t type, + CompilerType *target_type, // Can pass nullptr + bool check_cplusplus, + bool check_objc) override; + + bool + IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) override; + + bool + IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) override; + + bool + IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) override; + + bool + IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue) override; + + bool + IsScalarType (lldb::opaque_compiler_type_t type) override; + + bool + IsTypedefType (lldb::opaque_compiler_type_t type) override; + + bool + IsVoidType (lldb::opaque_compiler_type_t type) override; + + bool + SupportsLanguage (lldb::LanguageType language) override; + + static bool + GetCXXClassName (const CompilerType& type, std::string &class_name); + + static bool + GetObjCClassName (const CompilerType& type, std::string &class_name); + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + bool + GetCompleteType (lldb::opaque_compiler_type_t type) 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) override; + + lldb::LanguageType + GetMinimumLanguage (lldb::opaque_compiler_type_t type) override; + + lldb::TypeClass + GetTypeClass (lldb::opaque_compiler_type_t type) override; + + unsigned + GetTypeQualifiers(lldb::opaque_compiler_type_t type) override; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + // Using the current type, create a new typedef to that type using "typedef_name" + // as the name and "decl_ctx" as the decl context. + static CompilerType + CreateTypedefType (const CompilerType& type, + const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx); + + CompilerType + GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride) override; + + CompilerType + GetCanonicalType (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetFullyUnqualifiedType (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 + GetNonReferenceType (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetPointeeType (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetPointerType (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetLValueReferenceType (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetRValueReferenceType (lldb::opaque_compiler_type_t type) override; + + CompilerType + AddConstModifier (lldb::opaque_compiler_type_t type) override; + + CompilerType + AddVolatileModifier (lldb::opaque_compiler_type_t type) override; + + CompilerType + AddRestrictModifier (lldb::opaque_compiler_type_t type) override; + + CompilerType + CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx) override; + + // If the current object represents a typedef type, get the underlying type + CompilerType + GetTypedefedType (lldb::opaque_compiler_type_t type) override; + + static CompilerType + RemoveFastQualifiers (const CompilerType& type); + + //---------------------------------------------------------------------- + // Create related types using the current type's AST + //---------------------------------------------------------------------- + CompilerType + GetBasicTypeFromAST (lldb::BasicType basic_type) override; + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + uint64_t + GetByteSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) + { + return (GetBitSize (type, exe_scope) + 7) / 8; + } + + 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; + + 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; + + CompilerType + GetBuiltinTypeByName (const ConstString &name) override; + + lldb::BasicType + GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type) override; + + static lldb::BasicType + GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type, const ConstString &name); + + void + ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function const &callback) 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; + + 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; + + static uint32_t + GetNumPointeeChildren (clang::QualType type); + + 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> + // 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& child_indexes) override; + + size_t + GetNumTemplateArguments (lldb::opaque_compiler_type_t type) override; + + CompilerType + GetTemplateArgument (lldb::opaque_compiler_type_t type, + size_t idx, + lldb::TemplateArgumentKind &kind) override; + + CompilerType + GetTypeForFormatters (void* type) override; + +#define LLDB_INVALID_DECL_LEVEL UINT32_MAX + // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if + // child_decl_ctx could not be found in decl_ctx. + uint32_t + CountDeclLevels (clang::DeclContext *frame_decl_ctx, + clang::DeclContext *child_decl_ctx, + ConstString *child_name = nullptr, + CompilerType *child_type = nullptr); + + //---------------------------------------------------------------------- + // Modifying RecordType + //---------------------------------------------------------------------- + static clang::FieldDecl * + AddFieldToRecordType (const CompilerType& type, + const char *name, + const CompilerType &field_type, + lldb::AccessType access, + uint32_t bitfield_bit_size); + + static void + BuildIndirectFields (const CompilerType& type); + + static void + SetIsPacked (const CompilerType& type); + + static clang::VarDecl * + AddVariableToRecordType (const CompilerType& type, + const char *name, + const CompilerType &var_type, + lldb::AccessType access); + + clang::CXXMethodDecl * + AddMethodToCXXRecordType (lldb::opaque_compiler_type_t type, + const char *name, + const CompilerType &method_type, + lldb::AccessType access, + bool is_virtual, + bool is_static, + bool is_inline, + bool is_explicit, + bool is_attr_used, + bool is_artificial); + + // C++ Base Classes + 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); + + static bool + SetObjCSuperClass (const CompilerType& type, + const CompilerType &superclass_compiler_type); + + static bool + AddObjCClassProperty (const CompilerType& type, + const char *property_name, + const CompilerType &property_compiler_type, + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + ClangASTMetadata *metadata); + + static clang::ObjCMethodDecl * + AddMethodToObjCObjectType (const CompilerType& type, + const char *name, // the full symbol name as seen in the symbol table (lldb::opaque_compiler_type_t type, "-[NString stringWithCString:]") + const CompilerType &method_compiler_type, + lldb::AccessType access, + bool is_artificial); + + static bool + SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern); + + + static bool + CanImport (const CompilerType &type, lldb_private::ClangASTImporter &importer); + + static bool + Import (const CompilerType &type, lldb_private::ClangASTImporter &importer); + + static bool + GetHasExternalStorage (const CompilerType &type); + //------------------------------------------------------------------ + // Tag Declarations + //------------------------------------------------------------------ + static bool + StartTagDeclarationDefinition (const CompilerType &type); + + static bool + CompleteTagDeclarationDefinition (const CompilerType &type); + + //---------------------------------------------------------------------- + // 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); + + CompilerType + GetEnumerationIntegerType (lldb::opaque_compiler_type_t type); + + //------------------------------------------------------------------ + // Pointers & References + //------------------------------------------------------------------ + + // Call this function using the class type when you want to make a + // member pointer type to pointee_type. + static CompilerType + CreateMemberPointerType (const CompilerType& type, const CompilerType &pointee_type); + + // 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; + + //---------------------------------------------------------------------- + // 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 + 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; + + void + DumpTypeDescription (lldb::opaque_compiler_type_t type) override; // Dump to stdout + + void + DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) override; + + static void + DumpTypeName (const CompilerType &type); + + static clang::EnumDecl * + GetAsEnumDecl (const CompilerType& type); + + static clang::RecordDecl * + GetAsRecordDecl (const CompilerType& type); + + static clang::TagDecl * + GetAsTagDecl (const CompilerType& type); + + clang::CXXRecordDecl * + GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type); + + static clang::ObjCInterfaceDecl * + GetAsObjCInterfaceDecl (const CompilerType& type); + + static clang::QualType + GetQualType (const CompilerType& type) + { + // Make sure we have a clang type before making a clang::QualType + if (type.GetOpaqueQualType()) + { + ClangASTContext *ast = llvm::dyn_cast_or_null(type.GetTypeSystem()); + if (ast) + return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType()); + } + return clang::QualType(); + } + + static clang::QualType + GetCanonicalQualType (const CompilerType& type) + { + // Make sure we have a clang type before making a clang::QualType + ClangASTContext *ast = llvm::dyn_cast_or_null(type.GetTypeSystem()); + if (ast) + return clang::QualType::getFromOpaquePtr(type.GetOpaqueQualType()).getCanonicalType(); + return clang::QualType(); + } + + clang::ClassTemplateDecl * + ParseClassTemplateDecl (clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *parent_name, + int tag_decl_kind, + const ClangASTContext::TemplateParameterInfos &template_param_infos); + + clang::BlockDecl * + CreateBlockDeclaration (clang::DeclContext *ctx); + + clang::UsingDirectiveDecl * + CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl); + + clang::UsingDecl * + CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target); + + clang::VarDecl * + CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type); + protected: + static clang::QualType + GetQualType (lldb::opaque_compiler_type_t type) + { + if (type) + return clang::QualType::getFromOpaquePtr(type); + return clang::QualType(); + } + + static clang::QualType + GetCanonicalQualType (lldb::opaque_compiler_type_t type) + { + if (type) + return clang::QualType::getFromOpaquePtr(type).getCanonicalType(); + return clang::QualType(); + } + //------------------------------------------------------------------ // Classes that inherit from ClangASTContext can see and modify these //------------------------------------------------------------------ @@ -488,10 +1212,17 @@ protected: std::unique_ptr m_identifier_table_ap; std::unique_ptr m_selector_table_ap; std::unique_ptr m_builtins_ap; + std::unique_ptr m_dwarf_ast_parser_ap; + std::unique_ptr m_scratch_ast_source_ap; + std::unique_ptr m_mangle_ctx_ap; CompleteTagDeclCallback m_callback_tag_decl; CompleteObjCInterfaceDeclCallback m_callback_objc_decl; void * m_callback_baton; uint32_t m_pointer_byte_size; + bool m_ast_owned; + bool m_can_evaluate_expressions; + std::map> m_decl_objects; + private: //------------------------------------------------------------------ // For ClangASTContext only @@ -500,6 +1231,36 @@ private: const ClangASTContext& operator=(const ClangASTContext&); }; +class ClangASTContextForExpressions : public ClangASTContext +{ +public: + ClangASTContextForExpressions (Target &target); + + ~ClangASTContextForExpressions() override = default; + + UserExpression * + GetUserExpression (const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options) override; + + FunctionCaller * + GetFunctionCaller (const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name) override; + + UtilityFunction * + GetUtilityFunction(const char *text, const char *name) override; + + PersistentExpressionState * + GetPersistentExpressionState() override; +private: + lldb::TargetWP m_target_wp; + lldb::ClangPersistentVariablesUP m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. +}; + } // namespace lldb_private -#endif // liblldb_ClangASTContext_h_ +#endif // liblldb_ClangASTContext_h_ diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h index ee4fcada8a6d..8c3f8735c2e1 100644 --- a/include/lldb/Symbol/ClangASTImporter.h +++ b/include/lldb/Symbol/ClangASTImporter.h @@ -10,14 +10,21 @@ #ifndef liblldb_ClangASTImporter_h_ #define liblldb_ClangASTImporter_h_ +// C Includes +// C++ Includes #include +#include #include +#include -#include "lldb/lldb-types.h" +// Other libraries and framework includes #include "clang/AST/ASTImporter.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" + +// Project includes +#include "lldb/lldb-types.h" +#include "lldb/Symbol/CompilerDeclContext.h" namespace lldb_private { @@ -96,20 +103,24 @@ public: clang::ASTContext *src_ctx, clang::QualType type); - lldb::clang_type_t + lldb::opaque_compiler_type_t CopyType (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx, - lldb::clang_type_t type); - + lldb::opaque_compiler_type_t type); + + CompilerType + CopyType (ClangASTContext &dst, + const CompilerType &src_type); + clang::Decl * CopyDecl (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx, clang::Decl *decl); - lldb::clang_type_t + lldb::opaque_compiler_type_t DeportType (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx, - lldb::clang_type_t type); + lldb::opaque_compiler_type_t type); clang::Decl * DeportDecl (clang::ASTContext *dst_ctx, @@ -127,7 +138,10 @@ public: bool CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl); - + + bool + CompleteAndFetchChildren (clang::QualType type); + bool RequireCompleteType (clang::QualType type); @@ -155,7 +169,7 @@ public: // Namespace maps // - typedef std::vector < std::pair > NamespaceMap; + typedef std::vector < std::pair > NamespaceMap; typedef std::shared_ptr NamespaceMapSP; void RegisterNamespaceMap (const clang::NamespaceDecl *decl, @@ -199,12 +213,13 @@ public: void ForgetDestination (clang::ASTContext *dst_ctx); void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); + private: struct DeclOrigin { DeclOrigin () : - ctx(NULL), - decl(NULL) + ctx(nullptr), + decl(nullptr) { } @@ -230,7 +245,7 @@ private: bool Valid () { - return (ctx != NULL || decl != NULL); + return (ctx != nullptr || decl != nullptr); } clang::ASTContext *ctx; @@ -250,8 +265,8 @@ private: *source_ctx, master.m_file_manager, true /*minimal*/), - m_decls_to_deport(NULL), - m_decls_already_deported(NULL), + m_decls_to_deport(nullptr), + m_decls_already_deported(nullptr), m_master(master), m_source_ctx(source_ctx) { @@ -276,9 +291,9 @@ private: void ImportDefinitionTo (clang::Decl *to, clang::Decl *from); - clang::Decl *Imported (clang::Decl *from, clang::Decl *to); + clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override; - clang::Decl *GetOriginalDecl (clang::Decl *To); + clang::Decl *GetOriginalDecl(clang::Decl *To) override; std::set *m_decls_to_deport; std::set *m_decls_already_deported; @@ -297,7 +312,7 @@ private: m_minions (), m_origins (), m_namespace_maps (), - m_map_completer (NULL) + m_map_completer (nullptr) { } @@ -368,6 +383,6 @@ private: clang::FileManager m_file_manager; }; -} +} // namespace lldb_private -#endif +#endif // liblldb_ClangASTImporter_h_ diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h deleted file mode 100644 index 2524751e092e..000000000000 --- a/include/lldb/Symbol/ClangASTType.h +++ /dev/null @@ -1,684 +0,0 @@ -//===-- ClangASTType.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_ClangASTType_h_ -#define liblldb_ClangASTType_h_ - -#include -#include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h" -#include "clang/AST/Type.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -// A class that can carry around a clang ASTContext and a opaque clang -// QualType. A clang::QualType can be easily reconstructed from an -// opaque clang type and often the ASTContext is needed when doing -// various type related tasks, so this class allows both items to travel -// in a single very lightweight class that can be used. There are many -// static equivalents of the member functions that allow the ASTContext -// and the opaque clang QualType to be specified for ease of use and -// to avoid code duplication. -//---------------------------------------------------------------------- -class ClangASTType -{ -public: - //---------------------------------------------------------------------- - // Constructors and Destructors - //---------------------------------------------------------------------- - ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) : - m_type (type), - m_ast (ast_context) - { - } - - ClangASTType (clang::ASTContext *ast_context, clang::QualType qual_type); - - ClangASTType (const ClangASTType &rhs) : - m_type (rhs.m_type), - m_ast (rhs.m_ast) - { - } - - ClangASTType () : - m_type (0), - m_ast (0) - { - } - - ~ClangASTType(); - - //---------------------------------------------------------------------- - // Operators - //---------------------------------------------------------------------- - - const ClangASTType & - operator= (const ClangASTType &rhs) - { - m_type = rhs.m_type; - m_ast = rhs.m_ast; - return *this; - } - - - //---------------------------------------------------------------------- - // Tests - //---------------------------------------------------------------------- - - explicit operator bool () const - { - return m_type != NULL && m_ast != NULL; - } - - bool - operator < (const ClangASTType &rhs) const - { - if (m_ast == rhs.m_ast) - return m_type < rhs.m_type; - return m_ast < rhs.m_ast; - } - - bool - IsValid () const - { - return m_type != NULL && m_ast != NULL; - } - - bool - IsArrayType (ClangASTType *element_type, - uint64_t *size, - bool *is_incomplete) const; - - bool - IsVectorType (ClangASTType *element_type, - uint64_t *size) const; - - bool - IsArrayOfScalarType () const; - - bool - IsAggregateType () const; - - bool - IsBeingDefined () const; - - bool - IsCharType () const; - - bool - IsCompleteType () const; - - bool - IsConst() const; - - bool - IsCStringType (uint32_t &length) const; - - bool - IsCXXClassType () const; - - bool - IsDefined() const; - - bool - IsFloatingPointType (uint32_t &count, bool &is_complex) const; - - bool - IsFunctionType (bool *is_variadic_ptr = NULL) const; - - uint32_t - IsHomogeneousAggregate (ClangASTType* base_type_ptr) const; - - size_t - GetNumberOfFunctionArguments () const; - - ClangASTType - GetFunctionArgumentAtIndex (const size_t index) const; - - bool - IsVariadicFunctionType () const; - - bool - IsFunctionPointerType () const; - - bool - IsIntegerType (bool &is_signed) const; - - bool - IsObjCClassType () const; - - bool - IsObjCClassTypeAndHasIVars (bool check_superclass) const; - - bool - IsObjCObjectOrInterfaceType () const; - - bool - IsObjCObjectPointerType (ClangASTType *target_type = NULL); - - bool - IsPolymorphicClass () const; - - bool - IsPossibleCPlusPlusDynamicType (ClangASTType *target_type = NULL) const - { - return IsPossibleDynamicType (target_type, true, false); - } - - bool - IsPossibleDynamicType (ClangASTType *target_type, // Can pass NULL - bool check_cplusplus, - bool check_objc) const; - - - bool - IsPointerToScalarType () const; - - bool - IsRuntimeGeneratedType () const; - - bool - IsPointerType (ClangASTType *pointee_type = NULL) const; - - bool - IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const; - - bool - IsReferenceType (ClangASTType *pointee_type = nullptr, bool* is_rvalue = nullptr) const; - - bool - IsScalarType () const; - - bool - IsTypedefType () const; - - bool - IsVoidType () const; - - bool - GetCXXClassName (std::string &class_name) const; - - bool - GetObjCClassName (std::string &class_name); - - - //---------------------------------------------------------------------- - // Type Completion - //---------------------------------------------------------------------- - - bool - GetCompleteType () const; - - //---------------------------------------------------------------------- - // AST related queries - //---------------------------------------------------------------------- - - size_t - GetPointerByteSize () const; - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - - clang::ASTContext * - GetASTContext() const - { - return m_ast; - } - - ConstString - GetConstQualifiedTypeName () const; - - ConstString - GetConstTypeName () const; - - ConstString - GetTypeName () const; - - ConstString - GetDisplayTypeName () const; - - uint32_t - GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL) const; - - lldb::LanguageType - GetMinimumLanguage (); - - lldb::clang_type_t - GetOpaqueQualType() const - { - return m_type; - } - - lldb::TypeClass - GetTypeClass () const; - - void - SetClangType (clang::ASTContext *ast, lldb::clang_type_t type) - { - m_ast = ast; - m_type = type; - } - - void - SetClangType (clang::ASTContext *ast, clang::QualType qual_type); - - unsigned - GetTypeQualifiers() const; - - //---------------------------------------------------------------------- - // Creating related types - //---------------------------------------------------------------------- - - ClangASTType - AddConstModifier () const; - - ClangASTType - AddRestrictModifier () const; - - ClangASTType - AddVolatileModifier () const; - - // Using the current type, create a new typedef to that type using "typedef_name" - // as the name and "decl_ctx" as the decl context. - ClangASTType - CreateTypedefType (const char *typedef_name, - clang::DeclContext *decl_ctx) const; - - ClangASTType - GetArrayElementType (uint64_t *stride = nullptr) const; - - ClangASTType - GetCanonicalType () const; - - ClangASTType - GetFullyUnqualifiedType () const; - - // 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 () const; - - ClangASTType - GetFunctionArgumentTypeAtIndex (size_t idx) const; - - ClangASTType - GetFunctionReturnType () const; - - size_t - GetNumMemberFunctions () const; - - TypeMemberFunctionImpl - GetMemberFunctionAtIndex (size_t idx); - - ClangASTType - GetLValueReferenceType () const; - - ClangASTType - GetNonReferenceType () const; - - ClangASTType - GetPointeeType () const; - - ClangASTType - GetPointerType () const; - - ClangASTType - GetRValueReferenceType () const; - - // If the current object represents a typedef type, get the underlying type - ClangASTType - GetTypedefedType () const; - - ClangASTType - RemoveFastQualifiers () const; - - //---------------------------------------------------------------------- - // Create related types using the current type's AST - //---------------------------------------------------------------------- - ClangASTType - GetBasicTypeFromAST (lldb::BasicType basic_type) const; - - //---------------------------------------------------------------------- - // Exploring the type - //---------------------------------------------------------------------- - - uint64_t - GetByteSize (ExecutionContextScope *exe_scope) const; - - uint64_t - GetBitSize (ExecutionContextScope *exe_scope) const; - - lldb::Encoding - GetEncoding (uint64_t &count) const; - - lldb::Format - GetFormat () const; - - size_t - GetTypeBitAlign () const; - - uint32_t - GetNumChildren (bool omit_empty_base_classes) const; - - lldb::BasicType - GetBasicTypeEnumeration () const; - - static lldb::BasicType - GetBasicTypeEnumeration (const ConstString &name); - - uint32_t - GetNumDirectBaseClasses () const; - - uint32_t - GetNumVirtualBaseClasses () const; - - uint32_t - GetNumFields () const; - - ClangASTType - GetDirectBaseClassAtIndex (size_t idx, - uint32_t *bit_offset_ptr) const; - - ClangASTType - GetVirtualBaseClassAtIndex (size_t idx, - uint32_t *bit_offset_ptr) const; - - ClangASTType - GetFieldAtIndex (size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) const; - - uint32_t - GetIndexOfFieldWithName (const char* name, - ClangASTType* field_clang_type = NULL, - uint64_t *bit_offset_ptr = NULL, - uint32_t *bitfield_bit_size_ptr = NULL, - bool *is_bitfield_ptr = NULL) const; - - uint32_t - GetNumPointeeChildren () const; - - ClangASTType - GetChildClangTypeAtIndex (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) const; - - // 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 (const char *name, - bool omit_empty_base_classes) const; - - // 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> - // so we catch all names that match a given child name, not just the first. - size_t - GetIndexOfChildMemberWithName (const char *name, - bool omit_empty_base_classes, - std::vector& child_indexes) const; - - size_t - GetNumTemplateArguments () const; - - ClangASTType - GetTemplateArgument (size_t idx, - lldb::TemplateArgumentKind &kind) const; - - - //---------------------------------------------------------------------- - // Modifying RecordType - //---------------------------------------------------------------------- - clang::FieldDecl * - AddFieldToRecordType (const char *name, - const ClangASTType &field_type, - lldb::AccessType access, - uint32_t bitfield_bit_size); - - void - BuildIndirectFields (); - - void - SetIsPacked (); - - clang::VarDecl * - AddVariableToRecordType (const char *name, - const ClangASTType &var_type, - lldb::AccessType access); - - clang::CXXMethodDecl * - AddMethodToCXXRecordType (const char *name, - const ClangASTType &method_type, - lldb::AccessType access, - bool is_virtual, - bool is_static, - bool is_inline, - bool is_explicit, - bool is_attr_used, - bool is_artificial); - - // C++ Base Classes - clang::CXXBaseSpecifier * - CreateBaseClassSpecifier (lldb::AccessType access, - bool is_virtual, - bool base_of_class); - - static void - DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, - unsigned num_base_classes); - - bool - SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes, - unsigned num_base_classes); - - - bool - SetObjCSuperClass (const ClangASTType &superclass_clang_type); - - bool - AddObjCClassProperty (const char *property_name, - const ClangASTType &property_clang_type, - clang::ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - ClangASTMetadata *metadata); - - clang::ObjCMethodDecl * - AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") - const ClangASTType &method_clang_type, - lldb::AccessType access, - bool is_artificial); - - clang::DeclContext * - GetDeclContextForType () const; - - - bool - SetDefaultAccessForRecordFields (int default_accessibility, - int *assigned_accessibilities, - size_t num_assigned_accessibilities); - - bool - SetHasExternalStorage (bool has_extern); - - - //------------------------------------------------------------------ - // clang::TagType - //------------------------------------------------------------------ - - bool - SetTagTypeKind (int kind) const; - - //------------------------------------------------------------------ - // Tag Declarations - //------------------------------------------------------------------ - bool - StartTagDeclarationDefinition (); - - bool - CompleteTagDeclarationDefinition (); - - //---------------------------------------------------------------------- - // Modifying Enumeration types - //---------------------------------------------------------------------- - bool - AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_qual_type, - const Declaration &decl, - const char *name, - int64_t enum_value, - uint32_t enum_value_bit_size); - - - - ClangASTType - GetEnumerationIntegerType () const; - - - //------------------------------------------------------------------ - // Pointers & References - //------------------------------------------------------------------ - - // Call this function using the class type when you want to make a - // member pointer type to pointee_type. - ClangASTType - CreateMemberPointerType (const ClangASTType &pointee_type) const; - - - // Converts "s" to a floating point value and place resulting floating - // point bytes in the "dst" buffer. - size_t - ConvertStringToFloatValue (const char *s, - uint8_t *dst, - size_t dst_size) const; - //---------------------------------------------------------------------- - // Dumping types - //---------------------------------------------------------------------- - void - DumpValue (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); - - bool - DumpTypeValue (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); - - void - DumpSummary (ExecutionContext *exe_ctx, - Stream *s, - const DataExtractor &data, - lldb::offset_t data_offset, - size_t data_byte_size); - - void - DumpTypeDescription () const; // Dump to stdout - - void - DumpTypeDescription (Stream *s) const; - - bool - GetValueAsScalar (const DataExtractor &data, - lldb::offset_t data_offset, - size_t data_byte_size, - Scalar &value) const; - - bool - SetValueFromScalar (const Scalar &value, - Stream &strm); - - bool - ReadFromMemory (ExecutionContext *exe_ctx, - lldb::addr_t addr, - AddressType address_type, - DataExtractor &data); - - bool - WriteToMemory (ExecutionContext *exe_ctx, - lldb::addr_t addr, - AddressType address_type, - StreamString &new_value); - - clang::EnumDecl * - GetAsEnumDecl () const; - - - clang::RecordDecl * - GetAsRecordDecl () const; - - clang::CXXRecordDecl * - GetAsCXXRecordDecl () const; - - clang::ObjCInterfaceDecl * - GetAsObjCInterfaceDecl () const; - - void - Clear() - { - m_type = NULL; - m_ast = NULL; - } - - clang::QualType - GetQualType () const - { - if (m_type) - return clang::QualType::getFromOpaquePtr(m_type); - return clang::QualType(); - } - clang::QualType - GetCanonicalQualType () const - { - if (m_type) - return clang::QualType::getFromOpaquePtr(m_type).getCanonicalType(); - return clang::QualType(); - } - -private: - lldb::clang_type_t m_type; - clang::ASTContext *m_ast; - -}; - -bool operator == (const ClangASTType &lhs, const ClangASTType &rhs); -bool operator != (const ClangASTType &lhs, const ClangASTType &rhs); - - -} // namespace lldb_private - -#endif // #ifndef liblldb_ClangASTType_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h index 41bb235636f0..5a00aa0072ab 100644 --- a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h +++ b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h @@ -11,18 +11,17 @@ #define liblldb_ClangExternalASTSourceCallbacks_h_ // C Includes -// C++ Includes -#include -#include #include +// C++ Includes // Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" #include "clang/AST/CharUnits.h" // Project includes #include "lldb/lldb-enumerations.h" #include "lldb/Core/ClangForward.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" namespace lldb_private { @@ -30,7 +29,6 @@ namespace lldb_private { class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon { public: - typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); typedef void (*FindExternalVisibleDeclsByNameCallback)(void *baton, const clang::DeclContext *DC, clang::DeclarationName Name, llvm::SmallVectorImpl *results); @@ -62,7 +60,7 @@ public: { // This method only needs to be implemented if the AST source ever // passes back decl sets as VisibleDeclaration objects. - return 0; + return nullptr; } clang::Stmt * @@ -71,7 +69,7 @@ public: // This operation is meant to be used via a LazyOffsetPtr. It only // needs to be implemented if the AST source uses methods like // FunctionDecl::setLazyBody when building decls. - return 0; + return nullptr; } clang::Selector @@ -91,23 +89,18 @@ public: clang::CXXBaseSpecifier * GetExternalCXXBaseSpecifiers(uint64_t Offset) override { - return NULL; + return nullptr; } virtual void MaterializeVisibleDecls (const clang::DeclContext *decl_ctx) { - return; } - clang::ExternalLoadResult - FindExternalLexicalDecls(const clang::DeclContext *decl_ctx, bool (*isKindWeWant)(clang::Decl::Kind), - llvm::SmallVectorImpl &decls) override - { - // This is used to support iterating through an entire lexical context, - // which isn't something the debugger should ever need to do. - return clang::ELR_Failure; - } + void + FindExternalLexicalDecls(const clang::DeclContext *DC, + llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl &Result) override; bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName decl_name) override; @@ -119,6 +112,7 @@ public: llvm::DenseMap &FieldOffsets, llvm::DenseMap &BaseOffsets, llvm::DenseMap &VirtualBaseOffsets) override; + void SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, CompleteObjCInterfaceDeclCallback objc_decl_callback, @@ -138,10 +132,10 @@ public: { if (callback_baton == m_callback_baton) { - m_callback_tag_decl = NULL; - m_callback_objc_decl = NULL; - m_callback_find_by_name = NULL; - m_callback_layout_record_type = NULL; + m_callback_tag_decl = nullptr; + m_callback_objc_decl = nullptr; + m_callback_find_by_name = nullptr; + m_callback_layout_record_type = nullptr; } } @@ -158,4 +152,4 @@ protected: } // namespace lldb_private -#endif // liblldb_ClangExternalASTSourceCallbacks_h_ +#endif // liblldb_ClangExternalASTSourceCallbacks_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/include/lldb/Symbol/ClangExternalASTSourceCommon.h index 17650f7f14fd..711be42c15fb 100644 --- a/include/lldb/Symbol/ClangExternalASTSourceCommon.h +++ b/include/lldb/Symbol/ClangExternalASTSourceCommon.h @@ -20,6 +20,7 @@ // 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 @@ -27,8 +28,6 @@ #include #endif -#include "clang/AST/ExternalASTSource.h" - #ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG #undef NDEBUG #undef LLDB_DEFINED_NDEBUG_FOR_CLANG @@ -36,6 +35,11 @@ #include #endif +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ExternalASTSource.h" + +// Project includes #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/dwarf.h" @@ -124,8 +128,8 @@ public: return lldb::eLanguageTypeC_plus_plus; } return lldb::eLanguageTypeUnknown; - } + const char * GetObjectPtrName() const { @@ -137,7 +141,7 @@ public: return "this"; } else - return NULL; + return nullptr; } bool @@ -155,19 +159,19 @@ private: lldb::user_id_t m_user_id; uint64_t m_isa_ptr; }; + bool m_union_is_user_id : 1, m_union_is_isa_ptr : 1, m_has_object_ptr : 1, m_is_self : 1, m_is_dynamic_cxx : 1; - }; class ClangExternalASTSourceCommon : public clang::ExternalASTSource { public: ClangExternalASTSourceCommon(); - ~ClangExternalASTSourceCommon(); + ~ClangExternalASTSourceCommon() override; ClangASTMetadata *GetMetadata(const void *object); void SetMetadata(const void *object, ClangASTMetadata &metadata); @@ -175,12 +179,13 @@ public: static ClangExternalASTSourceCommon * Lookup(clang::ExternalASTSource *source); + private: typedef llvm::DenseMap MetadataMap; MetadataMap m_metadata; }; -} +} // namespace lldb_private -#endif +#endif // liblldb_ClangExternalASTSourceCommon_h diff --git a/include/lldb/Symbol/ClangNamespaceDecl.h b/include/lldb/Symbol/ClangNamespaceDecl.h deleted file mode 100644 index 13a4c0011aff..000000000000 --- a/include/lldb/Symbol/ClangNamespaceDecl.h +++ /dev/null @@ -1,105 +0,0 @@ -//===-- ClangNamespaceDecl.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_ClangNamespaceDecl_h_ -#define liblldb_ClangNamespaceDecl_h_ - -#include - -#include "lldb/lldb-public.h" -#include "lldb/Core/ClangForward.h" - -namespace lldb_private { - -class ClangNamespaceDecl -{ -public: - ClangNamespaceDecl () : - m_ast (NULL), - m_namespace_decl (NULL) - { - } - - ClangNamespaceDecl (clang::ASTContext *ast, clang::NamespaceDecl *namespace_decl) : - m_ast (ast), - m_namespace_decl (namespace_decl) - { - } - - ClangNamespaceDecl (const ClangNamespaceDecl &rhs) : - m_ast (rhs.m_ast), - m_namespace_decl (rhs.m_namespace_decl) - { - } - - const ClangNamespaceDecl & - operator = (const ClangNamespaceDecl &rhs) - { - m_ast = rhs.m_ast; - m_namespace_decl = rhs.m_namespace_decl; - return *this; - } - - //------------------------------------------------------------------ - /// Convert to bool operator. - /// - /// This allows code to check a ClangNamespaceDecl object to see if - /// it contains a valid namespace decl using code such as: - /// - /// @code - /// ClangNamespaceDecl ns_decl(...); - /// if (ns_decl) - /// { ... - /// @endcode - /// - /// @return - /// /b True this object contains a valid namespace decl, \b - /// false otherwise. - //------------------------------------------------------------------ - explicit operator bool() const - { - return m_ast != NULL && m_namespace_decl != NULL; - } - - clang::ASTContext * - GetASTContext() const - { - return m_ast; - } - - void - SetASTContext (clang::ASTContext *ast) - { - m_ast = ast; - } - - clang::NamespaceDecl * - GetNamespaceDecl () const - { - return m_namespace_decl; - } - - void - SetNamespaceDecl (clang::NamespaceDecl *namespace_decl) - { - m_namespace_decl = namespace_decl; - } - - std::string - GetQualifiedName () const; - -protected: - clang::ASTContext *m_ast; - clang::NamespaceDecl *m_namespace_decl; -}; - - -} // namespace lldb_private - -#endif // #ifndef liblldb_ClangNamespaceDecl_h_ diff --git a/include/lldb/Symbol/CompileUnit.h b/include/lldb/Symbol/CompileUnit.h index e0c069352bf4..0c331c38f8c6 100644 --- a/include/lldb/Symbol/CompileUnit.h +++ b/include/lldb/Symbol/CompileUnit.h @@ -11,6 +11,7 @@ #define liblldb_CompUnit_h_ #include "lldb/lldb-enumerations.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Function.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/ModuleChild.h" @@ -66,9 +67,12 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// + /// @param[in] is_optimized + /// true if this compile unit was compiled with optimization. + /// /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language); + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized); //------------------------------------------------------------------ /// Construct with a module, file spec, UID and language. @@ -98,15 +102,17 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// + /// @param[in] is_optimized + /// true if this compile unit was compiled with optimization. + /// /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language); + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized); //------------------------------------------------------------------ /// Destructor //------------------------------------------------------------------ - virtual - ~CompileUnit(); + ~CompileUnit() override; //------------------------------------------------------------------ /// Add a function to this compile unit. @@ -125,22 +131,22 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - CalculateSymbolContext(SymbolContext* sc); + void + CalculateSymbolContext(SymbolContext* sc) override; - virtual lldb::ModuleSP - CalculateSymbolContextModule (); + lldb::ModuleSP + CalculateSymbolContextModule() override; - virtual CompileUnit * - CalculateSymbolContextCompileUnit (); + CompileUnit * + CalculateSymbolContextCompileUnit() override; //------------------------------------------------------------------ /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - DumpSymbolContext(Stream *s); + void + DumpSymbolContext(Stream *s) override; lldb::LanguageType GetLanguage(); @@ -245,6 +251,9 @@ public: LineTable* GetLineTable (); + DebugMacros* + GetDebugMacros (); + //------------------------------------------------------------------ /// Get the compile unit's support file list. /// @@ -339,6 +348,9 @@ public: void SetLineTable(LineTable* line_table); + void + SetDebugMacros(const DebugMacrosSP &debug_macros); + //------------------------------------------------------------------ /// Set accessor for the variable list. /// @@ -406,6 +418,22 @@ public: SymbolContextList &sc_list); + //------------------------------------------------------------------ + /// Get whether compiler optimizations were enabled for this compile unit + /// + /// "optimized" means that the debug experience may be difficult + /// for the user to understand. Variables may not be available when + /// the developer would expect them, stepping through the source lines + /// in the function may appear strange, etc. + /// + /// @return + /// Returns 'true' if this compile unit was compiled with + /// optimization. 'false' indicates that either the optimization + /// is unknown, or this compile unit was built without optimization. + //------------------------------------------------------------------ + bool + GetIsOptimized (); + protected: void *m_user_data; ///< User data for the SymbolFile parser to store information into. lldb::LanguageType m_language; ///< The programming language enumeration value. @@ -416,7 +444,9 @@ protected: ///< compile unit. FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations. std::unique_ptr m_line_table_ap; ///< Line table that will get parsed on demand. + DebugMacrosSP m_debug_macros_sp; ///< Debug macros that will get parsed on demand. lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. + bool m_is_optimized; /// eLazyBoolYes if this compile unit was compiled with optimization. private: enum @@ -425,8 +455,9 @@ private: flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics? flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? - flagsParsedLanguage = (1u << 4), ///< Have we parsed the line table already? - flagsParsedImportedModules = (1u << 5) ///< Have we parsed the imported modules already? + flagsParsedLanguage = (1u << 4), ///< Have we parsed the language already? + flagsParsedImportedModules = (1u << 5), ///< Have we parsed the imported modules already? + flagsParsedDebugMacros = (1u << 6) ///< Have we parsed the debug macros already? }; DISALLOW_COPY_AND_ASSIGN (CompileUnit); @@ -434,4 +465,4 @@ private: } // namespace lldb_private -#endif // liblldb_CompUnit_h_ +#endif // liblldb_CompUnit_h_ diff --git a/include/lldb/Symbol/CompilerDecl.h b/include/lldb/Symbol/CompilerDecl.h new file mode 100644 index 000000000000..b749e79b459a --- /dev/null +++ b/include/lldb/Symbol/CompilerDecl.h @@ -0,0 +1,135 @@ +//===-- CompilerDecl.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_CompilerDecl_h_ +#define liblldb_CompilerDecl_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Symbol/CompilerType.h" + +namespace lldb_private { + +class CompilerDecl +{ +public: + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + CompilerDecl () : + m_type_system (nullptr), + m_opaque_decl (nullptr) + { + } + + CompilerDecl (TypeSystem *type_system, void *decl) : + m_type_system (type_system), + m_opaque_decl (decl) + { + } + + ~CompilerDecl () + { + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + explicit operator bool () const + { + return IsValid (); + } + + bool + operator < (const CompilerDecl &rhs) const + { + if (m_type_system == rhs.m_type_system) + return m_opaque_decl < rhs.m_opaque_decl; + return m_type_system < rhs.m_type_system; + } + + bool + IsValid () const + { + return m_type_system != nullptr && m_opaque_decl != nullptr; + } + + bool + IsClang () const; + + //---------------------------------------------------------------------- + // Object linked to the decl + //---------------------------------------------------------------------- + lldb::VariableSP + GetAsVariable (); + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + TypeSystem * + GetTypeSystem() const + { + return m_type_system; + } + + void * + GetOpaqueDecl() const + { + return m_opaque_decl; + } + + void + SetDecl (TypeSystem* type_system, void* decl) + { + m_type_system = type_system; + m_opaque_decl = decl; + } + + void + Clear() + { + m_type_system = nullptr; + m_opaque_decl = nullptr; + } + + ConstString + GetName () const; + + ConstString + GetMangledName () const; + + CompilerDeclContext + GetDeclContext() const; + + // If this decl represents a function, return the return type + CompilerType + GetFunctionReturnType() const; + + // If this decl represents a function, return the number of arguments for the function + size_t + GetNumFunctionArguments() const; + + // If this decl represents a function, return the argument type given a zero based argument index + CompilerType + GetFunctionArgumentType (size_t arg_idx) const; + +private: + TypeSystem *m_type_system; + void *m_opaque_decl; +}; + +bool operator == (const CompilerDecl &lhs, const CompilerDecl &rhs); +bool operator != (const CompilerDecl &lhs, const CompilerDecl &rhs); + + +} // namespace lldb_private + +#endif // #ifndef liblldb_CompilerDecl_h_ diff --git a/include/lldb/Symbol/CompilerDeclContext.h b/include/lldb/Symbol/CompilerDeclContext.h new file mode 100644 index 000000000000..70399b2dbb37 --- /dev/null +++ b/include/lldb/Symbol/CompilerDeclContext.h @@ -0,0 +1,146 @@ +//===-- CompilerDeclContext.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_CompilerDeclContext_h_ +#define liblldb_CompilerDeclContext_h_ + +#include + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +class CompilerDeclContext +{ +public: + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + CompilerDeclContext () : + m_type_system (nullptr), + m_opaque_decl_ctx (nullptr) + { + } + + CompilerDeclContext (TypeSystem *type_system, void *decl_ctx) : + m_type_system (type_system), + m_opaque_decl_ctx (decl_ctx) + { + } + + ~CompilerDeclContext() + { + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + explicit operator bool () const + { + return IsValid (); + } + + bool + operator < (const CompilerDeclContext &rhs) const + { + if (m_type_system == rhs.m_type_system) + return m_opaque_decl_ctx < rhs.m_opaque_decl_ctx; + return m_type_system < rhs.m_type_system; + } + + bool + IsValid () const + { + return m_type_system != nullptr && m_opaque_decl_ctx != nullptr; + } + + bool + IsClang () const; + + std::vector + FindDeclByName (ConstString name); + + //---------------------------------------------------------------------- + /// Checks if this decl context represents a method of a class. + /// + /// @param[out] language_ptr + /// If non NULL and \b true is returned from this function, + /// this will indicate if the language that respresents the method. + /// + /// @param[out] is_instance_method_ptr + /// If non NULL and \b true is returned from this function, + /// this will indicate if the method is an instance function (true) + /// or a class method (false indicating the function is static, or + /// doesn't require an instance of the class to be called). + /// + /// @param[out] language_object_name_ptr + /// If non NULL and \b true is returned from this function, + /// this will indicate if implicit object name for the language + /// like "this" for C++, and "self" for Objective C. + /// + /// @return + /// Returns true if this is a decl context that represents a method + /// in a struct, union or class. + //---------------------------------------------------------------------- + bool + IsClassMethod (lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, + ConstString *language_object_name_ptr); + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + TypeSystem * + GetTypeSystem() const + { + return m_type_system; + } + + void * + GetOpaqueDeclContext() const + { + return m_opaque_decl_ctx; + } + + void + SetDeclContext (TypeSystem* type_system, void* decl_ctx) + { + m_type_system = type_system; + m_opaque_decl_ctx = decl_ctx; + } + + void + Clear() + { + m_type_system = nullptr; + m_opaque_decl_ctx = nullptr; + } + + ConstString + GetName () const; + + bool + IsStructUnionOrClass () const; + +private: + TypeSystem *m_type_system; + void *m_opaque_decl_ctx; + +}; + +bool operator == (const CompilerDeclContext &lhs, const CompilerDeclContext &rhs); +bool operator != (const CompilerDeclContext &lhs, const CompilerDeclContext &rhs); + + +} // namespace lldb_private + +#endif // #ifndef liblldb_CompilerDeclContext_h_ diff --git a/include/lldb/Symbol/CompilerType.h b/include/lldb/Symbol/CompilerType.h new file mode 100644 index 000000000000..4f3ecc54ba1a --- /dev/null +++ b/include/lldb/Symbol/CompilerType.h @@ -0,0 +1,571 @@ +//===-- CompilerType.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_CompilerType_h_ +#define liblldb_CompilerType_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class that can carry around a clang ASTContext and a opaque clang +// QualType. A clang::QualType can be easily reconstructed from an +// opaque clang type and often the ASTContext is needed when doing +// various type related tasks, so this class allows both items to travel +// in a single very lightweight class that can be used. There are many +// static equivalents of the member functions that allow the ASTContext +// and the opaque clang QualType to be specified for ease of use and +// to avoid code duplication. +//---------------------------------------------------------------------- +class CompilerType +{ +public: + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + CompilerType (TypeSystem *type_system, lldb::opaque_compiler_type_t type); + CompilerType (clang::ASTContext *ast_context, clang::QualType qual_type); + + CompilerType (const CompilerType &rhs) : + m_type (rhs.m_type), + m_type_system (rhs.m_type_system) + { + } + + CompilerType () : + m_type (nullptr), + m_type_system (nullptr) + { + } + + ~CompilerType(); + + //---------------------------------------------------------------------- + // Operators + //---------------------------------------------------------------------- + + const CompilerType & + operator= (const CompilerType &rhs) + { + m_type = rhs.m_type; + m_type_system = rhs.m_type_system; + return *this; + } + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + explicit operator bool () const + { + return m_type != nullptr && m_type_system != nullptr; + } + + bool + operator < (const CompilerType &rhs) const + { + if (m_type_system == rhs.m_type_system) + return m_type < rhs.m_type; + return m_type_system < rhs.m_type_system; + } + + bool + IsValid () const + { + return m_type != nullptr && m_type_system != nullptr; + } + + bool + IsArrayType (CompilerType *element_type, + uint64_t *size, + bool *is_incomplete) const; + + bool + IsVectorType (CompilerType *element_type, + uint64_t *size) const; + + bool + IsArrayOfScalarType () const; + + bool + IsAggregateType () const; + + bool + IsAnonymousType () const; + + bool + IsBeingDefined () const; + + bool + IsCharType () const; + + bool + IsCompleteType () const; + + bool + IsConst() const; + + bool + IsCStringType (uint32_t &length) const; + + bool + IsDefined() const; + + bool + IsFloatingPointType (uint32_t &count, bool &is_complex) const; + + bool + IsFunctionType(bool *is_variadic_ptr = nullptr) const; + + uint32_t + IsHomogeneousAggregate (CompilerType* base_type_ptr) const; + + size_t + GetNumberOfFunctionArguments () const; + + CompilerType + GetFunctionArgumentAtIndex (const size_t index) const; + + bool + IsVariadicFunctionType () const; + + bool + IsFunctionPointerType () const; + + bool + IsIntegerType (bool &is_signed) const; + + bool + IsPolymorphicClass () const; + + bool + IsPossibleCPlusPlusDynamicType(CompilerType *target_type = nullptr) const + { + return IsPossibleDynamicType (target_type, true, false); + } + + bool + IsPossibleDynamicType(CompilerType *target_type, // Can pass nullptr + bool check_cplusplus, + bool check_objc) const; + + bool + IsPointerToScalarType () const; + + bool + IsRuntimeGeneratedType () const; + + bool + IsPointerType(CompilerType *pointee_type = nullptr) const; + + bool + IsPointerOrReferenceType(CompilerType *pointee_type = nullptr) const; + + bool + IsReferenceType(CompilerType *pointee_type = nullptr, bool* is_rvalue = nullptr) const; + + bool + ShouldTreatScalarValueAsAddress () const; + + bool + IsScalarType () const; + + bool + IsTypedefType () const; + + bool + IsVoidType () const; + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + bool + GetCompleteType () const; + + //---------------------------------------------------------------------- + // AST related queries + //---------------------------------------------------------------------- + + size_t + GetPointerByteSize () const; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + TypeSystem * + GetTypeSystem() const + { + return m_type_system; + } + + ConstString + GetConstQualifiedTypeName () const; + + ConstString + GetConstTypeName () const; + + ConstString + GetTypeName () const; + + ConstString + GetDisplayTypeName () const; + + uint32_t + GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr) const; + + lldb::LanguageType + GetMinimumLanguage (); + + lldb::opaque_compiler_type_t + GetOpaqueQualType() const + { + return m_type; + } + + lldb::TypeClass + GetTypeClass () const; + + void + SetCompilerType (TypeSystem* type_system, lldb::opaque_compiler_type_t type); + + void + SetCompilerType (clang::ASTContext *ast, clang::QualType qual_type); + + unsigned + GetTypeQualifiers() const; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + CompilerType + GetArrayElementType(uint64_t *stride = nullptr) const; + + CompilerType + GetCanonicalType () const; + + CompilerType + GetFullyUnqualifiedType () const; + + // 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 () const; + + CompilerType + GetFunctionArgumentTypeAtIndex (size_t idx) const; + + CompilerType + GetFunctionReturnType () const; + + size_t + GetNumMemberFunctions () const; + + TypeMemberFunctionImpl + GetMemberFunctionAtIndex (size_t idx); + + //---------------------------------------------------------------------- + // If this type is a reference to a type (L value or R value reference), + // return a new type with the reference removed, else return the current + // type itself. + //---------------------------------------------------------------------- + CompilerType + GetNonReferenceType () const; + + //---------------------------------------------------------------------- + // If this type is a pointer type, return the type that the pointer + // points to, else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + GetPointeeType () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType that is a pointer to this type + //---------------------------------------------------------------------- + CompilerType + GetPointerType () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType that is a L value reference to this type if + // this type is valid and the type system supports L value references, + // else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + GetLValueReferenceType () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType that is a R value reference to this type if + // this type is valid and the type system supports R value references, + // else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + GetRValueReferenceType () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType adds a const modifier to this type if + // this type is valid and the type system supports const modifiers, + // else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + AddConstModifier () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType adds a volatile modifier to this type if + // this type is valid and the type system supports volatile modifiers, + // else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + AddVolatileModifier () const; + + //---------------------------------------------------------------------- + // Return a new CompilerType adds a restrict modifier to this type if + // this type is valid and the type system supports restrict modifiers, + // else return an invalid type. + //---------------------------------------------------------------------- + CompilerType + AddRestrictModifier () const; + + //---------------------------------------------------------------------- + // Create a typedef to this type using "name" as the name of the typedef + // this type is valid and the type system supports typedefs, else return + // an invalid type. + //---------------------------------------------------------------------- + CompilerType + CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const; + + // If the current object represents a typedef type, get the underlying type + CompilerType + GetTypedefedType () const; + + //---------------------------------------------------------------------- + // Create related types using the current type's AST + //---------------------------------------------------------------------- + CompilerType + GetBasicTypeFromAST (lldb::BasicType basic_type) const; + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + uint64_t + GetByteSize (ExecutionContextScope *exe_scope) const; + + uint64_t + GetBitSize (ExecutionContextScope *exe_scope) const; + + lldb::Encoding + GetEncoding (uint64_t &count) const; + + lldb::Format + GetFormat () const; + + size_t + GetTypeBitAlign () const; + + uint32_t + GetNumChildren (bool omit_empty_base_classes) const; + + lldb::BasicType + GetBasicTypeEnumeration () const; + + static lldb::BasicType + GetBasicTypeEnumeration (const ConstString &name); + + //---------------------------------------------------------------------- + // If this type is an enumeration, iterate through all of its enumerators + // using a callback. If the callback returns true, keep iterating, else + // abort the iteration. + //---------------------------------------------------------------------- + void + ForEachEnumerator (std::function const &callback) const; + + uint32_t + GetNumFields () const; + + CompilerType + GetFieldAtIndex (size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const; + + uint32_t + GetNumDirectBaseClasses () const; + + uint32_t + GetNumVirtualBaseClasses () const; + + CompilerType + GetDirectBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + CompilerType + GetVirtualBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + uint32_t + GetIndexOfFieldWithName(const char* name, + CompilerType* field_compiler_type = nullptr, + uint64_t *bit_offset_ptr = nullptr, + uint32_t *bitfield_bit_size_ptr = nullptr, + bool *is_bitfield_ptr = nullptr) const; + + CompilerType + GetChildCompilerTypeAtIndex (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) const; + + // 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 (const char *name, + bool omit_empty_base_classes) const; + + // 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> + // so we catch all names that match a given child name, not just the first. + size_t + GetIndexOfChildMemberWithName (const char *name, + bool omit_empty_base_classes, + std::vector& child_indexes) const; + + size_t + GetNumTemplateArguments () const; + + CompilerType + GetTemplateArgument (size_t idx, + lldb::TemplateArgumentKind &kind) const; + + CompilerType + GetTypeForFormatters () const; + + LazyBool + ShouldPrintAsOneLiner (ValueObject* valobj) const; + + bool + IsMeaninglessWithoutDynamicResolution () const; + + //------------------------------------------------------------------ + // Pointers & References + //------------------------------------------------------------------ + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + size_t + ConvertStringToFloatValue (const char *s, + uint8_t *dst, + size_t dst_size) const; + + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + void + DumpValue (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); + + bool + DumpTypeValue (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); + + void + DumpSummary (ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size); + + void + DumpTypeDescription () const; // Dump to stdout + + void + DumpTypeDescription (Stream *s) const; + + bool + GetValueAsScalar (const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + Scalar &value) const; + + bool + SetValueFromScalar (const Scalar &value, + Stream &strm); + + bool + ReadFromMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + DataExtractor &data); + + bool + WriteToMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + StreamString &new_value); + + void + Clear() + { + m_type = nullptr; + m_type_system = nullptr; + } + +private: + lldb::opaque_compiler_type_t m_type; + TypeSystem *m_type_system; +}; + +bool operator == (const CompilerType &lhs, const CompilerType &rhs); +bool operator != (const CompilerType &lhs, const CompilerType &rhs); + +} // namespace lldb_private + +#endif // liblldb_CompilerType_h_ diff --git a/include/lldb/Symbol/DebugMacros.h b/include/lldb/Symbol/DebugMacros.h new file mode 100644 index 000000000000..24bf03a8c3b1 --- /dev/null +++ b/include/lldb/Symbol/DebugMacros.h @@ -0,0 +1,140 @@ +//===-- DebugMacros.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_DebugMacros_h_ +#define liblldb_DebugMacros_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +class CompileUnit; +class DebugMacros; +typedef std::shared_ptr DebugMacrosSP; + +class DebugMacroEntry +{ +public: + enum EntryType + { + INVALID, + DEFINE, + UNDEF, + START_FILE, + END_FILE, + INDIRECT + }; + +public: + static DebugMacroEntry + CreateDefineEntry(uint32_t line, const char *str); + + static DebugMacroEntry + CreateUndefEntry(uint32_t line, const char *str); + + static DebugMacroEntry + CreateStartFileEntry(uint32_t line, uint32_t debug_line_file_idx); + + static DebugMacroEntry + CreateEndFileEntry(); + + static DebugMacroEntry + CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp); + + DebugMacroEntry() : m_type(INVALID) { } + + ~DebugMacroEntry() = default; + + EntryType + GetType() const + { + return m_type; + } + + uint64_t + GetLineNumber() const + { + return m_line; + } + + ConstString + GetMacroString() const + { + return m_str; + } + + const FileSpec& GetFileSpec(CompileUnit *comp_unit) const; + + DebugMacros * + GetIndirectDebugMacros() const + { + return m_debug_macros_sp.get(); + } + +private: + DebugMacroEntry(EntryType type, + uint32_t line, + uint32_t debug_line_file_idx, + const char *str); + + DebugMacroEntry(EntryType type, + const DebugMacrosSP &debug_macros_sp); + + EntryType m_type:3; + uint32_t m_line:29; + uint32_t m_debug_line_file_idx; + ConstString m_str; + DebugMacrosSP m_debug_macros_sp; +}; + +class DebugMacros +{ +public: + DebugMacros() = default; + + ~DebugMacros() = default; + + void + AddMacroEntry(const DebugMacroEntry &entry) + { + m_macro_entries.push_back(entry); + } + + size_t + GetNumMacroEntries() const + { + return m_macro_entries.size(); + } + + DebugMacroEntry + GetMacroEntryAtIndex(const size_t index) const + { + if (index < m_macro_entries.size()) + return m_macro_entries[index]; + else + return DebugMacroEntry(); + } + +private: + DISALLOW_COPY_AND_ASSIGN(DebugMacros); + + std::vector m_macro_entries; +}; + +} // namespace lldb_private + +#endif // liblldb_DebugMacros_h_ diff --git a/include/lldb/Symbol/FuncUnwinders.h b/include/lldb/Symbol/FuncUnwinders.h index 0d4aabb5fd57..728b4c6fcb32 100644 --- a/include/lldb/Symbol/FuncUnwinders.h +++ b/include/lldb/Symbol/FuncUnwinders.h @@ -102,6 +102,9 @@ public: lldb::UnwindPlanSP GetCompactUnwindUnwindPlan (Target &target, int current_offset); + lldb::UnwindPlanSP + GetArmUnwindUnwindPlan (Target &target, int current_offset); + lldb::UnwindPlanSP GetArchDefaultUnwindPlan (Thread &thread); @@ -122,6 +125,7 @@ private: lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp; lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp; // augmented by assembly inspection so it's valid everywhere std::vector m_unwind_plan_compact_unwind; + lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp; lldb::UnwindPlanSP m_unwind_plan_fast_sp; lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; @@ -132,6 +136,7 @@ private: m_tried_unwind_plan_eh_frame:1, m_tried_unwind_plan_eh_frame_augmented:1, m_tried_unwind_plan_compact_unwind:1, + m_tried_unwind_plan_arm_unwind:1, m_tried_unwind_fast:1, m_tried_unwind_arch_default:1, m_tried_unwind_arch_default_at_func_entry:1; diff --git a/include/lldb/Symbol/Function.h b/include/lldb/Symbol/Function.h index 30c8f168e5f1..cd2df9b6078f 100644 --- a/include/lldb/Symbol/Function.h +++ b/include/lldb/Symbol/Function.h @@ -10,7 +10,6 @@ #ifndef liblldb_Function_h_ #define liblldb_Function_h_ -#include "lldb/Core/ClangForward.h" #include "lldb/Core/AddressRange.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Declaration.h" @@ -147,7 +146,6 @@ protected: Declaration m_declaration; ///< Information describing where this function information was defined. }; - //---------------------------------------------------------------------- /// @class InlineFunctionInfo Function.h "lldb/Symbol/Function.h" /// @brief A class that describes information for an inlined function. @@ -203,7 +201,7 @@ public: //------------------------------------------------------------------ /// Destructor. //------------------------------------------------------------------ - ~InlineFunctionInfo(); + ~InlineFunctionInfo() override; //------------------------------------------------------------------ /// Compare two inlined function information objects. @@ -294,8 +292,8 @@ public: /// /// @see ConstString::StaticMemorySize () //------------------------------------------------------------------ - virtual size_t - MemorySize() const; + size_t + MemorySize() const override; private: //------------------------------------------------------------------ @@ -415,24 +413,24 @@ public: //------------------------------------------------------------------ /// Destructor. //------------------------------------------------------------------ - ~Function (); + ~Function() override; //------------------------------------------------------------------ /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - CalculateSymbolContext(SymbolContext* sc); + void + CalculateSymbolContext(SymbolContext* sc) override; - virtual lldb::ModuleSP - CalculateSymbolContextModule (); + lldb::ModuleSP + CalculateSymbolContextModule() override; - virtual CompileUnit * - CalculateSymbolContextCompileUnit (); + CompileUnit * + CalculateSymbolContextCompileUnit() override; - virtual Function * - CalculateSymbolContextFunction (); + Function * + CalculateSymbolContextFunction() override; const AddressRange & GetAddressRange() @@ -550,8 +548,8 @@ public: /// @return /// The DeclContext, or NULL if none exists. //------------------------------------------------------------------ - clang::DeclContext * - GetClangDeclContext(); + CompilerDeclContext + GetDeclContext(); //------------------------------------------------------------------ /// Get accessor for the type that describes the function @@ -573,8 +571,8 @@ public: const Type* GetType() const; - ClangASTType - GetClangType (); + CompilerType + GetCompilerType (); uint32_t GetPrologueByteSize (); @@ -600,8 +598,8 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - DumpSymbolContext(Stream *s); + void + DumpSymbolContext(Stream *s) override; //------------------------------------------------------------------ /// Get the memory cost of this object. @@ -616,6 +614,42 @@ public: size_t MemorySize () const; + //------------------------------------------------------------------ + /// Get whether compiler optimizations were enabled for this function + /// + /// The debug information may provide information about whether this + /// function was compiled with optimization or not. In this case, + /// "optimized" means that the debug experience may be difficult + /// for the user to understand. Variables may not be available when + /// the developer would expect them, stepping through the source lines + /// in the function may appear strange, etc. + /// + /// @return + /// Returns 'true' if this function was compiled with + /// optimization. 'false' indicates that either the optimization + /// is unknown, or this function was built without optimization. + //------------------------------------------------------------------ + bool + GetIsOptimized (); + + //------------------------------------------------------------------ + /// Get whether this function represents a 'top-level' function + /// + /// The concept of a top-level function is language-specific, mostly + /// meant to represent the notion of scripting-style code that has + /// global visibility of the variables/symbols/functions/... + /// defined within the containing file/module + /// + /// If stopped in a top-level function, LLDB will expose global variables + /// as-if locals in the 'frame variable' command + /// + /// @return + /// Returns 'true' if this function is a top-level function, + /// 'false' otherwise. + //------------------------------------------------------------------ + bool + IsTopLevelFunction (); + lldb::DisassemblerSP GetInstructions (const ExecutionContext &exe_ctx, const char *flavor, @@ -634,8 +668,6 @@ protected: flagsCalculatedPrologueSize = (1 << 0) ///< Have we already tried to calculate the prologue size? }; - - //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ @@ -654,4 +686,4 @@ private: } // namespace lldb_private -#endif // liblldb_Function_h_ +#endif // liblldb_Function_h_ diff --git a/include/lldb/Symbol/GoASTContext.h b/include/lldb/Symbol/GoASTContext.h new file mode 100644 index 000000000000..3de98da59958 --- /dev/null +++ b/include/lldb/Symbol/GoASTContext.h @@ -0,0 +1,402 @@ +//===-- 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 +#include +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/CompilerType.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 &languages_for_types, std::set &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(); + } + + lldb::VariableSP + DeclGetVariable (void *opaque_decl) override + { + return lldb::VariableSP(); + } + + void + DeclLinkToObject (void *opaque_decl, std::shared_ptr object) override + { + } + + //---------------------------------------------------------------------- + // CompilerDeclContext functions + //---------------------------------------------------------------------- + + bool + DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override + { + return false; + } + + ConstString + DeclContextGetName(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 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> + // 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 &child_indexes) override; + + size_t + GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override + { + return 0; + } + + CompilerType + GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) override + { + return CompilerType(); + } + + //---------------------------------------------------------------------- + // 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> TypeMap; + int m_pointer_byte_size; + int m_int_byte_size; + std::unique_ptr m_types; + std::unique_ptr 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(const char *expr, const char *expr_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/LineEntry.h b/include/lldb/Symbol/LineEntry.h index 082caea3b12f..374c04a7fcec 100644 --- a/include/lldb/Symbol/LineEntry.h +++ b/include/lldb/Symbol/LineEntry.h @@ -140,6 +140,32 @@ struct LineEntry static int Compare (const LineEntry& lhs, const LineEntry& rhs); + //------------------------------------------------------------------ + /// Give the range for this LineEntry + any additional LineEntries for + /// this same source line that are contiguous. + /// + /// A compiler may emit multiple line entries for a single source line, + /// e.g. to indicate subexpressions at different columns. This method + /// will get the AddressRange for all of the LineEntries for this source + /// line that are contiguous. + // + /// Line entries with a line number of 0 are treated specially - these + /// are compiler-generated line table entries that the user did not + /// write in their source code, and we want to skip past in the debugger. + /// If this LineEntry is for line 32, and the following LineEntry is for + /// line 0, we will extend the range to include the AddressRange of the + /// line 0 LineEntry (and it will include the range of the following + /// LineEntries that match either 32 or 0.) + /// + /// If the initial LineEntry this method is called on is a line #0, only + /// the range of contiuous LineEntries with line #0 will be included in + /// the complete range. + /// + /// @return + /// The contiguous AddressRange for this source line. + //------------------------------------------------------------------ + AddressRange + GetSameLineContiguousAddressRange () const; //------------------------------------------------------------------ // Member variables. diff --git a/include/lldb/Symbol/LineTable.h b/include/lldb/Symbol/LineTable.h index 3e25ad17e94e..cbad9bf590c2 100644 --- a/include/lldb/Symbol/LineTable.h +++ b/include/lldb/Symbol/LineTable.h @@ -10,8 +10,12 @@ #ifndef liblldb_LineTable_h_ #define liblldb_LineTable_h_ +// C Includes +// C++ Includes #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Core/ModuleChild.h" @@ -30,7 +34,7 @@ public: LineSequence (); virtual - ~LineSequence() {} + ~LineSequence() = default; virtual void Clear() = 0; @@ -143,14 +147,14 @@ public: /// /// @param[out] index_ptr /// A pointer to a 32 bit integer that will get the actual line - /// entry index if it is not NULL. + /// entry index if it is not nullptr. /// /// @return /// Returns \b true if \a so_addr is contained in a line entry /// in this line table, \b false otherwise. //------------------------------------------------------------------ bool - FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = NULL); + FindLineEntryByAddress(const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = nullptr); //------------------------------------------------------------------ /// Find a line entry index that has a matching file index and @@ -269,7 +273,6 @@ public: LinkLineTable (const FileRangeMap &file_range_map); protected: - struct Entry { Entry () : @@ -343,12 +346,12 @@ protected: return 0; } - class LessThanBinaryPredicate { public: LessThanBinaryPredicate(LineTable *line_table); bool operator() (const LineTable::Entry&, const LineTable::Entry&) const; + protected: LineTable *m_line_table; }; @@ -396,16 +399,12 @@ protected: class LineSequenceImpl : public LineSequence { public: - LineSequenceImpl() : - LineSequence() - {} + LineSequenceImpl() = default; - virtual - ~LineSequenceImpl() - {} + ~LineSequenceImpl() override = default; - virtual void - Clear(); + void + Clear() override; entry_collection m_entries; ///< The collection of line entries in this sequence. }; @@ -419,4 +418,4 @@ private: } // namespace lldb_private -#endif // liblldb_LineTable_h_ +#endif // liblldb_LineTable_h_ diff --git a/include/lldb/Symbol/ObjectContainer.h b/include/lldb/Symbol/ObjectContainer.h index 679e8f03b67a..eeda1c4ae19d 100644 --- a/include/lldb/Symbol/ObjectContainer.h +++ b/include/lldb/Symbol/ObjectContainer.h @@ -14,7 +14,6 @@ // C++ Includes // Other libraries and framework includes // Project includes - #include "lldb/lldb-private.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Host/FileSpec.h" @@ -71,10 +70,7 @@ public: /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. //------------------------------------------------------------------ - virtual - ~ObjectContainer() - { - } + ~ObjectContainer() override = default; //------------------------------------------------------------------ /// Dump a description of this object to a Stream. @@ -188,7 +184,7 @@ public: /// /// @return /// Returns a pointer to the object file of the requested \a - /// arch and optional \a name. Returns NULL of no such object + /// arch and optional \a name. Returns nullptr of no such object /// file exists in the container. //------------------------------------------------------------------ virtual lldb::ObjectFileSP @@ -203,19 +199,19 @@ public: virtual ObjectFile * GetObjectFileAtIndex (uint32_t object_idx) { - return NULL; + return nullptr; } virtual ObjectContainer * GetObjectContainerAtIndex (uint32_t object_idx) { - return NULL; + return nullptr; } virtual const char * GetObjectNameAtIndex (uint32_t object_idx) const { - return NULL; + return nullptr; } protected: @@ -233,4 +229,4 @@ private: } // namespace lldb_private -#endif // liblldb_ObjectContainer_h_ +#endif // liblldb_ObjectContainer_h_ diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h index ff00ac26e67e..4b0a2f9ff936 100644 --- a/include/lldb/Symbol/ObjectFile.h +++ b/include/lldb/Symbol/ObjectFile.h @@ -125,8 +125,7 @@ public: /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. //------------------------------------------------------------------ - virtual - ~ObjectFile(); + ~ObjectFile() override; //------------------------------------------------------------------ /// Dump a description of this object to a Stream. @@ -369,12 +368,11 @@ public: /// The list of sections contained in this object file. //------------------------------------------------------------------ virtual SectionList * - GetSectionList (); + GetSectionList (bool update_module_section_list = true); virtual void CreateSections (SectionList &unified_section_list) = 0; - //------------------------------------------------------------------ /// Notify the ObjectFile that the file addresses in the Sections /// for this module have been changed. @@ -595,7 +593,6 @@ public: virtual lldb_private::Address GetHeaderAddress () { return Address(m_memory_addr);} - virtual uint32_t GetNumThreadContexts () { @@ -767,7 +764,6 @@ public: return 0; } - //------------------------------------------------------------------ /// Return true if this file is a dynamic link editor (dyld) /// @@ -823,6 +819,7 @@ public: lldb::offset_t section_offset, void *dst, size_t dst_len) const; + virtual size_t ReadSectionData (const Section *section, DataExtractor& section_data) const; @@ -843,7 +840,11 @@ public: { return symbol_name.str(); } - + + static lldb::SymbolType + GetSymbolTypeFromName (llvm::StringRef name, + lldb::SymbolType symbol_type_hint = lldb::eSymbolTypeUndefined); + protected: //------------------------------------------------------------------ // Member variables. @@ -880,5 +881,4 @@ private: } // namespace lldb_private -#endif // liblldb_ObjectFile_h_ - +#endif // liblldb_ObjectFile_h_ diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h index f9438b006c4e..c77d3dea4bd2 100644 --- a/include/lldb/Symbol/Symbol.h +++ b/include/lldb/Symbol/Symbol.h @@ -333,6 +333,7 @@ public: { return m_demangled_is_synthesized; } + void SetDemangledNameIsSynthesized(bool b) { @@ -354,22 +355,22 @@ public: /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - CalculateSymbolContext (SymbolContext *sc); + void + CalculateSymbolContext(SymbolContext *sc) override; - virtual lldb::ModuleSP - CalculateSymbolContextModule (); + lldb::ModuleSP + CalculateSymbolContextModule() override; - virtual Symbol * - CalculateSymbolContextSymbol (); + Symbol * + CalculateSymbolContextSymbol() override; //------------------------------------------------------------------ /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) /// /// @see SymbolContextScope //------------------------------------------------------------------ - virtual void - DumpSymbolContext (Stream *s); + void + DumpSymbolContext(Stream *s) override; lldb::DisassemblerSP GetInstructions (const ExecutionContext &exe_ctx, @@ -411,4 +412,4 @@ protected: } // namespace lldb_private -#endif // liblldb_Symbol_h_ +#endif // liblldb_Symbol_h_ diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h index c48505e1064a..9cb709d24011 100644 --- a/include/lldb/Symbol/SymbolContext.h +++ b/include/lldb/Symbol/SymbolContext.h @@ -7,12 +7,17 @@ // //===----------------------------------------------------------------------===// - #ifndef liblldb_SymbolContext_h_ #define liblldb_SymbolContext_h_ +// C Includes +// C++ Includes +#include +#include #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/Mangled.h" @@ -22,6 +27,7 @@ namespace lldb_private { class SymbolContextScope; + //---------------------------------------------------------------------- /// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h" /// @brief Defines a symbol context baton that can be handed other debug @@ -36,11 +42,10 @@ class SymbolContextScope; class SymbolContext { public: - //------------------------------------------------------------------ /// Default constructor. /// - /// Initialize all pointer members to NULL and all struct members + /// Initialize all pointer members to nullptr and all struct members /// to their default state. //------------------------------------------------------------------ SymbolContext (); @@ -81,24 +86,23 @@ public: /// A Symbol pointer to the symbol for this context. //------------------------------------------------------------------ explicit - SymbolContext (const lldb::TargetSP &target_sp, - const lldb::ModuleSP &module_sp, - CompileUnit *comp_unit = NULL, - Function *function = NULL, - Block *block = NULL, - LineEntry *line_entry = NULL, - Symbol *symbol = NULL); + SymbolContext(const lldb::TargetSP &target_sp, + const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = nullptr, + Function *function = nullptr, + Block *block = nullptr, + LineEntry *line_entry = nullptr, + Symbol *symbol = nullptr); // This version sets the target to a NULL TargetSP if you don't know it. explicit - SymbolContext (const lldb::ModuleSP &module_sp, - CompileUnit *comp_unit = NULL, - Function *function = NULL, - Block *block = NULL, - LineEntry *line_entry = NULL, - Symbol *symbol = NULL); + SymbolContext(const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = nullptr, + Function *function = nullptr, + Block *block = nullptr, + LineEntry *line_entry = nullptr, + Symbol *symbol = nullptr); - ~SymbolContext (); //------------------------------------------------------------------ /// Copy constructor /// @@ -109,6 +113,8 @@ public: //------------------------------------------------------------------ SymbolContext (const SymbolContext& rhs); + ~SymbolContext (); + //------------------------------------------------------------------ /// Assignment operator. /// @@ -127,7 +133,7 @@ public: //------------------------------------------------------------------ /// Clear the object's state. /// - /// Resets all pointer members to NULL, and clears any class objects + /// Resets all pointer members to nullptr, and clears any class objects /// to their default state. //------------------------------------------------------------------ void @@ -203,14 +209,14 @@ public: /// /// Address range priority is as follows: /// - line_entry address range if line_entry is valid and eSymbolContextLineEntry is set in \a scope - /// - block address range if block is not NULL and eSymbolContextBlock is set in \a scope - /// - function address range if function is not NULL and eSymbolContextFunction is set in \a scope - /// - symbol address range if symbol is not NULL and eSymbolContextSymbol is set in \a scope + /// - block address range if block is not nullptr and eSymbolContextBlock is set in \a scope + /// - function address range if function is not nullptr and eSymbolContextFunction is set in \a scope + /// - symbol address range if symbol is not nullptr and eSymbolContextSymbol is set in \a scope /// /// @param[in] scope /// A mask of symbol context bits telling this function which /// address ranges it can use when trying to extract one from - /// the valid (non-NULL) symbol context classes. + /// the valid (non-nullptr) symbol context classes. /// /// @param[in] range_idx /// The address range index to grab. Since many functions and @@ -239,7 +245,6 @@ public: bool use_inline_block_range, AddressRange &range) const; - void GetDescription(Stream *s, lldb::DescriptionLevel level, @@ -248,7 +253,9 @@ public: uint32_t GetResolvedMask () const; - + lldb::LanguageType + GetLanguage () const; + //------------------------------------------------------------------ /// Find a block that defines the function represented by this /// symbol context. @@ -268,12 +275,11 @@ public: /// /// @return /// The block object pointer that defines the function that is - /// represented by this symbol context object, NULL otherwise. + /// represented by this symbol context object, nullptr otherwise. //------------------------------------------------------------------ Block * GetFunctionBlock (); - //------------------------------------------------------------------ /// If this symbol context represents a function that is a method, /// return true and provide information about the method. @@ -298,6 +304,14 @@ public: bool &is_instance_method, ConstString &language_object_name); + //------------------------------------------------------------------ + /// Sorts the types in TypeMap according to SymbolContext + /// to TypeList + /// + //------------------------------------------------------------------ + void + SortTypeList(TypeMap &type_map, TypeList &type_list) const; + //------------------------------------------------------------------ /// Find a name of the innermost function for the symbol context. /// @@ -315,7 +329,6 @@ public: ConstString GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const; - //------------------------------------------------------------------ /// Get the line entry that corresponds to the function. /// @@ -377,7 +390,6 @@ public: Variable * variable; ///< The global variable matching the given query }; - class SymbolContextSpecifier { public: @@ -427,7 +439,6 @@ private: std::string m_class_name; std::unique_ptr m_address_range_ap; uint32_t m_type; // Or'ed bits from SpecificationType - }; //---------------------------------------------------------------------- @@ -479,6 +490,7 @@ public: uint32_t AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function); + //------------------------------------------------------------------ /// Clear the object's state. /// @@ -558,6 +570,7 @@ public: bool RemoveContextAtIndex (size_t idx); + //------------------------------------------------------------------ /// Get accessor for a symbol context list size. /// @@ -600,4 +613,4 @@ bool operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs); } // namespace lldb_private -#endif // liblldb_SymbolContext_h_ +#endif // liblldb_SymbolContext_h_ diff --git a/include/lldb/Symbol/SymbolContextScope.h b/include/lldb/Symbol/SymbolContextScope.h index a02b4523a4c0..212d8e6df233 100644 --- a/include/lldb/Symbol/SymbolContextScope.h +++ b/include/lldb/Symbol/SymbolContextScope.h @@ -72,7 +72,7 @@ class SymbolContextScope { public: virtual - ~SymbolContextScope () {} + ~SymbolContextScope() = default; //------------------------------------------------------------------ /// Reconstruct the object's symbol context into \a sc. @@ -87,7 +87,6 @@ public: virtual void CalculateSymbolContext (SymbolContext *sc) = 0; - virtual lldb::ModuleSP CalculateSymbolContextModule () { @@ -97,25 +96,25 @@ public: virtual CompileUnit * CalculateSymbolContextCompileUnit () { - return NULL; + return nullptr; } virtual Function * CalculateSymbolContextFunction () { - return NULL; + return nullptr; } virtual Block * CalculateSymbolContextBlock () { - return NULL; + return nullptr; } virtual Symbol * CalculateSymbolContextSymbol () { - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -134,4 +133,4 @@ public: } // namespace lldb_private -#endif // liblldb_SymbolContextScope_h_ +#endif // liblldb_SymbolContextScope_h_ diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h index 0efe034235d5..e27b32d01f68 100644 --- a/include/lldb/Symbol/SymbolFile.h +++ b/include/lldb/Symbol/SymbolFile.h @@ -12,8 +12,9 @@ #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Type.h" namespace lldb_private { @@ -55,8 +56,7 @@ public: { } - virtual - ~SymbolFile() + ~SymbolFile() override { } @@ -123,33 +123,43 @@ public: 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 ParseImportedModules (const SymbolContext &sc, std::vector &imported_modules) = 0; virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0; virtual size_t ParseTypes (const SymbolContext& sc) = 0; virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0; virtual Type* ResolveTypeUID (lldb::user_id_t type_uid) = 0; - virtual bool ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) = 0; - virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) { return NULL; } - virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) { return NULL; } + virtual bool CompleteType (CompilerType &compiler_type) = 0; + virtual void ParseDeclsForContext (CompilerDeclContext decl_ctx) {} + virtual CompilerDecl GetDeclForUID (lldb::user_id_t uid) { return CompilerDecl(); } + virtual CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) { return CompilerDeclContext(); } + virtual CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) { return CompilerDeclContext(); } virtual uint32_t ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) = 0; - virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) = 0; - virtual uint32_t FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) = 0; - virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) = 0; - virtual uint32_t FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; - virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; - virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) = 0; + virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list); + virtual uint32_t FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables); + virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, 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); + 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, TypeMap& types); + virtual size_t FindTypes (const std::vector &context, bool append, TypeMap& types); + // virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0; virtual TypeList * GetTypeList (); virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list) = 0; - virtual ClangASTContext & - GetClangASTContext (); - virtual ClangNamespaceDecl + + virtual lldb_private::TypeSystem * + GetTypeSystemForLanguage (lldb::LanguageType language); + + virtual CompilerDeclContext FindNamespace (const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *parent_namespace_decl) = 0; + const CompilerDeclContext *parent_decl_ctx) + { + return CompilerDeclContext(); + } ObjectFile* GetObjectFile() { return m_obj_file; } const ObjectFile* GetObjectFile() const { return m_obj_file; } @@ -163,16 +173,15 @@ public: { } - protected: ObjectFile* m_obj_file; // The object file that symbols can be extracted from. uint32_t m_abilities; bool m_calculated_abilities; + private: DISALLOW_COPY_AND_ASSIGN (SymbolFile); }; - } // namespace lldb_private -#endif // liblldb_SymbolFile_h_ +#endif // liblldb_SymbolFile_h_ diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h index 248918af2833..19461718ed13 100644 --- a/include/lldb/Symbol/SymbolVendor.h +++ b/include/lldb/Symbol/SymbolVendor.h @@ -15,9 +15,8 @@ #include "lldb/lldb-private.h" #include "lldb/Core/ModuleChild.h" #include "lldb/Core/PluginInterface.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/TypeList.h" - +#include "lldb/Symbol/TypeMap.h" namespace lldb_private { @@ -45,8 +44,7 @@ public: //------------------------------------------------------------------ SymbolVendor(const lldb::ModuleSP &module_sp); - virtual - ~SymbolVendor(); + ~SymbolVendor() override; void AddSymbolFileRepresentation(const lldb::ObjectFileSP &objfile_sp); @@ -63,6 +61,9 @@ public: virtual bool ParseCompileUnitLineTable (const SymbolContext& sc); + virtual bool + ParseCompileUnitDebugMacros (const SymbolContext& sc); + virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files); @@ -97,7 +98,7 @@ public: virtual size_t FindGlobalVariables (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, VariableList& variables); @@ -110,7 +111,7 @@ public: virtual size_t FindFunctions (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, @@ -125,15 +126,18 @@ public: virtual size_t FindTypes (const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, - TypeList& types); + TypeMap& types); - virtual ClangNamespaceDecl + virtual size_t + FindTypes (const std::vector &context, bool append, TypeMap& types); + + virtual CompilerDeclContext FindNamespace (const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *parent_namespace_decl); + const CompilerDeclContext *parent_decl_ctx); virtual size_t GetNumCompileUnits(); @@ -189,11 +193,11 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual ConstString - GetPluginName(); + ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: //------------------------------------------------------------------ @@ -215,7 +219,6 @@ private: DISALLOW_COPY_AND_ASSIGN (SymbolVendor); }; - } // namespace lldb_private -#endif // liblldb_SymbolVendor_h_ +#endif // liblldb_SymbolVendor_h_ diff --git a/include/lldb/Symbol/TaggedASTType.h b/include/lldb/Symbol/TaggedASTType.h index c44a5356f86d..82431a562287 100644 --- a/include/lldb/Symbol/TaggedASTType.h +++ b/include/lldb/Symbol/TaggedASTType.h @@ -10,33 +10,33 @@ #ifndef liblldb_TaggedASTType_h_ #define liblldb_TaggedASTType_h_ -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" namespace lldb_private { // For cases in which there are multiple classes of types that are not // interchangeable, to allow static type checking. -template class TaggedASTType : public ClangASTType +template class TaggedASTType : public CompilerType { public: - TaggedASTType (const ClangASTType &clang_type) : - ClangASTType(clang_type) + TaggedASTType (const CompilerType &compiler_type) : + CompilerType(compiler_type) { } - TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : - ClangASTType(ast_context, type) + TaggedASTType (lldb::opaque_compiler_type_t type, TypeSystem * type_system) : + CompilerType(type_system, type) { } TaggedASTType (const TaggedASTType &tw) : - ClangASTType(tw) + CompilerType(tw) { } TaggedASTType () : - ClangASTType() + CompilerType() { } @@ -47,7 +47,7 @@ public: TaggedASTType &operator= (const TaggedASTType &tw) { - ClangASTType::operator= (tw); + CompilerType::operator= (tw); return *this; } }; diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h index c1784cb364a8..224e0a112df3 100644 --- a/include/lldb/Symbol/Type.h +++ b/include/lldb/Symbol/Type.h @@ -14,7 +14,8 @@ #include "lldb/Core/ClangForward.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/UserID.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Declaration.h" #include "llvm/ADT/APSInt.h" @@ -23,6 +24,31 @@ namespace lldb_private { +//---------------------------------------------------------------------- +// CompilerContext allows an array of these items to be passed to +// perform detailed lookups in SymbolVendor and SymbolFile functions. +//---------------------------------------------------------------------- +struct CompilerContext +{ + CompilerContext (CompilerContextKind t, const ConstString &n) : + type(t), + name(n) + { + } + + bool + operator == (const CompilerContext &rhs) const + { + return type == rhs.type && name == rhs.name; + } + + void + Dump () const; + + CompilerContextKind type; + ConstString name; +}; + class SymbolFileType : public std::enable_shared_from_this, public UserID @@ -34,6 +60,9 @@ class SymbolFileType : { } + SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp); + + ~SymbolFileType () { } @@ -92,8 +121,8 @@ public: lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, const Declaration& decl, - const ClangASTType &clang_qual_type, - ResolveState clang_type_resolve_state); + const CompilerType &compiler_qual_type, + ResolveState compiler_type_resolve_state); // This makes an invalid type. Used for functions that return a Type when they // get an error. @@ -239,22 +268,19 @@ public: // Get the clang type, and resolve definitions for any // class/struct/union/enum types completely. - ClangASTType - GetClangFullType (); + CompilerType + GetFullCompilerType (); // Get the clang type, and resolve definitions enough so that the type could // have layout performed. This allows ptrs and refs to class/struct/union/enum // types remain forward declarations. - ClangASTType - GetClangLayoutType (); + CompilerType + GetLayoutCompilerType (); // Get the clang type and leave class/struct/union/enum types as forward // declarations if they haven't already been fully defined. - ClangASTType - GetClangForwardType (); - - ClangASTContext & - GetClangASTContext (); + CompilerType + GetForwardCompilerType (); static int Compare(const Type &a, const Type &b); @@ -275,12 +301,6 @@ public: uint32_t GetEncodingMask (); - ClangASTType - CreateClangTypedefType (Type *typedef_type, Type *base_type); - - bool - IsRealObjCClass(); - bool IsCompleteObjCClass() { @@ -302,14 +322,14 @@ protected: EncodingDataType m_encoding_uid_type; uint64_t m_byte_size; Declaration m_decl; - ClangASTType m_clang_type; + CompilerType m_compiler_type; struct Flags { #ifdef __GNUC__ // using unsigned type here to work around a very noisy gcc warning - unsigned clang_type_resolve_state : 2; + unsigned compiler_type_resolve_state : 2; #else - ResolveState clang_type_resolve_state : 2; + ResolveState compiler_type_resolve_state : 2; #endif bool is_complete_objc_class : 1; } m_flags; @@ -318,7 +338,7 @@ protected: GetEncodingType (); bool - ResolveClangType (ResolveState clang_type_resolve_state); + ResolveClangType (ResolveState compiler_type_resolve_state); }; // these classes are used to back the SBType* objects @@ -327,28 +347,28 @@ class TypePair { public: TypePair () : - clang_type(), + compiler_type(), type_sp() { } - TypePair (ClangASTType type) : - clang_type(type), + TypePair (CompilerType type) : + compiler_type(type), type_sp() { } TypePair (lldb::TypeSP type) : - clang_type(), - type_sp(type) + compiler_type(), + type_sp(type) { - clang_type = type_sp->GetClangForwardType(); + compiler_type = type_sp->GetForwardCompilerType (); } bool IsValid () const { - return clang_type.IsValid() || (type_sp.get() != nullptr); + return compiler_type.IsValid() || (type_sp.get() != nullptr); } explicit operator bool () const @@ -359,21 +379,21 @@ public: bool operator == (const TypePair& rhs) const { - return clang_type == rhs.clang_type && + return compiler_type == rhs.compiler_type && type_sp.get() == rhs.type_sp.get(); } bool operator != (const TypePair& rhs) const { - return clang_type != rhs.clang_type || + return compiler_type != rhs.compiler_type || type_sp.get() != rhs.type_sp.get(); } void Clear () { - clang_type.Clear(); + compiler_type.Clear(); type_sp.reset(); } @@ -382,8 +402,8 @@ public: { if (type_sp) return type_sp->GetName(); - if (clang_type) - return clang_type.GetTypeName(); + if (compiler_type) + return compiler_type.GetTypeName(); return ConstString (); } @@ -391,24 +411,24 @@ public: GetDisplayTypeName () const { if (type_sp) - return type_sp->GetClangForwardType().GetDisplayTypeName(); - if (clang_type) - return clang_type.GetDisplayTypeName(); + return type_sp->GetForwardCompilerType ().GetDisplayTypeName(); + if (compiler_type) + return compiler_type.GetDisplayTypeName(); return ConstString(); } void - SetType (ClangASTType type) + SetType (CompilerType type) { type_sp.reset(); - clang_type = type; + compiler_type = type; } void SetType (lldb::TypeSP type) { type_sp = type; - clang_type = type_sp->GetClangForwardType(); + compiler_type = type_sp->GetForwardCompilerType (); } lldb::TypeSP @@ -417,72 +437,76 @@ public: return type_sp; } - ClangASTType - GetClangASTType () const + CompilerType + GetCompilerType () const { - return clang_type; + return compiler_type; } - ClangASTType + CompilerType GetPointerType () const { if (type_sp) - return type_sp->GetClangLayoutType().GetPointerType(); - return clang_type.GetPointerType(); + return type_sp->GetForwardCompilerType().GetPointerType(); + return compiler_type.GetPointerType(); } - ClangASTType + CompilerType GetPointeeType () const { if (type_sp) - return type_sp->GetClangFullType().GetPointeeType(); - return clang_type.GetPointeeType(); + return type_sp->GetForwardCompilerType ().GetPointeeType(); + return compiler_type.GetPointeeType(); } - ClangASTType + CompilerType GetReferenceType () const { if (type_sp) - return type_sp->GetClangLayoutType().GetLValueReferenceType(); - return clang_type.GetLValueReferenceType(); + return type_sp->GetForwardCompilerType ().GetLValueReferenceType(); + else + return compiler_type.GetLValueReferenceType(); } - ClangASTType + CompilerType GetTypedefedType () const { if (type_sp) - return type_sp->GetClangFullType().GetTypedefedType(); - return clang_type.GetTypedefedType(); + return type_sp->GetForwardCompilerType ().GetTypedefedType(); + else + return compiler_type.GetTypedefedType(); } - ClangASTType + CompilerType GetDereferencedType () const { if (type_sp) - return type_sp->GetClangFullType().GetNonReferenceType(); - return clang_type.GetNonReferenceType(); + return type_sp->GetForwardCompilerType ().GetNonReferenceType(); + else + return compiler_type.GetNonReferenceType(); } - ClangASTType + CompilerType GetUnqualifiedType () const { if (type_sp) - return type_sp->GetClangLayoutType().GetFullyUnqualifiedType(); - return clang_type.GetFullyUnqualifiedType(); + return type_sp->GetForwardCompilerType ().GetFullyUnqualifiedType(); + else + return compiler_type.GetFullyUnqualifiedType(); } - ClangASTType + CompilerType GetCanonicalType () const { if (type_sp) - return type_sp->GetClangFullType().GetCanonicalType(); - return clang_type.GetCanonicalType(); + return type_sp->GetForwardCompilerType ().GetCanonicalType(); + return compiler_type.GetCanonicalType(); } - clang::ASTContext * - GetClangASTContext () const + TypeSystem * + GetTypeSystem () const { - return clang_type.GetASTContext(); + return compiler_type.GetTypeSystem(); } lldb::ModuleSP @@ -493,10 +517,13 @@ public: return lldb::ModuleSP(); } protected: - ClangASTType clang_type; + CompilerType compiler_type; lldb::TypeSP type_sp; }; +// the two classes here are used by the public API as a backend to +// the SBType and SBTypeList classes + class TypeImpl { public: @@ -509,28 +536,28 @@ public: TypeImpl (const lldb::TypeSP &type_sp); - TypeImpl (const ClangASTType &clang_type); + TypeImpl (const CompilerType &compiler_type); - TypeImpl (const lldb::TypeSP &type_sp, const ClangASTType &dynamic); + TypeImpl (const lldb::TypeSP &type_sp, const CompilerType &dynamic); - TypeImpl (const ClangASTType &clang_type, const ClangASTType &dynamic); + TypeImpl (const CompilerType &compiler_type, const CompilerType &dynamic); - TypeImpl (const TypePair &pair, const ClangASTType &dynamic); + TypeImpl (const TypePair &pair, const CompilerType &dynamic); void SetType (const lldb::TypeSP &type_sp); void - SetType (const ClangASTType &clang_type); + SetType (const CompilerType &compiler_type); void - SetType (const lldb::TypeSP &type_sp, const ClangASTType &dynamic); + SetType (const lldb::TypeSP &type_sp, const CompilerType &dynamic); void - SetType (const ClangASTType &clang_type, const ClangASTType &dynamic); + SetType (const CompilerType &compiler_type, const CompilerType &dynamic); void - SetType (const TypePair &pair, const ClangASTType &dynamic); + SetType (const TypePair &pair, const CompilerType &dynamic); TypeImpl& operator = (const TypeImpl& rhs); @@ -575,11 +602,11 @@ public: TypeImpl GetCanonicalType() const; - ClangASTType - GetClangASTType (bool prefer_dynamic); + CompilerType + GetCompilerType (bool prefer_dynamic); - clang::ASTContext * - GetClangASTContext (bool prefer_dynamic); + TypeSystem * + GetTypeSystem (bool prefer_dynamic); bool GetDescription (lldb_private::Stream &strm, @@ -592,7 +619,7 @@ private: lldb::ModuleWP m_module_wp; TypePair m_static_type; - ClangASTType m_dynamic_type; + CompilerType m_dynamic_type; }; class TypeListImpl @@ -750,7 +777,7 @@ class TypeAndOrName public: TypeAndOrName (); TypeAndOrName (lldb::TypeSP &type_sp); - TypeAndOrName (const ClangASTType &clang_type); + TypeAndOrName (const CompilerType &compiler_type); TypeAndOrName (const char *type_str); TypeAndOrName (const TypeAndOrName &rhs); TypeAndOrName (ConstString &type_const_string); @@ -772,10 +799,10 @@ public: return m_type_pair.GetTypeSP(); } - ClangASTType - GetClangASTType () const + CompilerType + GetCompilerType () const { - return m_type_pair.GetClangASTType(); + return m_type_pair.GetCompilerType(); } void @@ -788,7 +815,7 @@ public: SetTypeSP (lldb::TypeSP type_sp); void - SetClangASTType (ClangASTType clang_type); + SetCompilerType (CompilerType compiler_type); bool IsEmpty () const; @@ -800,12 +827,12 @@ public: HasTypeSP () const; bool - HasClangASTType () const; + HasCompilerType () const; bool HasType () const { - return HasTypeSP() || HasClangASTType(); + return HasTypeSP() || HasCompilerType(); } void @@ -825,60 +852,43 @@ class TypeMemberFunctionImpl { public: TypeMemberFunctionImpl() : - m_type(), - m_objc_method_decl(nullptr), + m_type (), + m_decl (), m_name(), - m_kind(lldb::eMemberFunctionKindUnknown) + m_kind (lldb::eMemberFunctionKindUnknown) { } - TypeMemberFunctionImpl (const ClangASTType& type, + TypeMemberFunctionImpl (const CompilerType& type, + const CompilerDecl& decl, const std::string& name, const lldb::MemberFunctionKind& kind) : - m_type(type), - m_objc_method_decl(nullptr), + m_type (type), + m_decl (decl), m_name(name), - m_kind(kind) - { - } - - TypeMemberFunctionImpl (clang::ObjCMethodDecl *method, - const std::string& name, - const lldb::MemberFunctionKind& kind) : - m_type(), - m_objc_method_decl(method), - m_name(name), - m_kind(kind) - { - } - - TypeMemberFunctionImpl (const TypeMemberFunctionImpl& rhs) : - m_type(rhs.m_type), - m_objc_method_decl(rhs.m_objc_method_decl), - m_name(rhs.m_name), - m_kind(rhs.m_kind) + m_kind (kind) { } - TypeMemberFunctionImpl& - operator = (const TypeMemberFunctionImpl& rhs); - bool IsValid (); ConstString GetName () const; - - ClangASTType + + ConstString + GetMangledName () const; + + CompilerType GetType () const; - ClangASTType + CompilerType GetReturnType () const; size_t GetNumArguments () const; - ClangASTType + CompilerType GetArgumentAtIndex (size_t idx) const; lldb::MemberFunctionKind @@ -892,8 +902,8 @@ protected: GetPrintableTypeName (); private: - ClangASTType m_type; - clang::ObjCMethodDecl *m_objc_method_decl; + CompilerType m_type; + CompilerDecl m_decl; ConstString m_name; lldb::MemberFunctionKind m_kind; }; @@ -909,8 +919,9 @@ public: { } - TypeEnumMemberImpl (const clang::EnumConstantDecl* enum_member_decl, - const lldb_private::ClangASTType& integer_type); + TypeEnumMemberImpl (const lldb::TypeImplSP &integer_type_sp, + const ConstString &name, + const llvm::APSInt &value); TypeEnumMemberImpl (const TypeEnumMemberImpl& rhs) : m_integer_type_sp(rhs.m_integer_type_sp), diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h index 4f3f2c9bdbeb..f3642576ddcb 100644 --- a/include/lldb/Symbol/TypeList.h +++ b/include/lldb/Symbol/TypeList.h @@ -13,7 +13,7 @@ #include "lldb/lldb-private.h" #include "lldb/Symbol/Type.h" #include "lldb/Utility/Iterable.h" -#include +#include #include namespace lldb_private { @@ -24,7 +24,7 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - TypeList(); + TypeList(); virtual ~TypeList(); @@ -44,17 +44,14 @@ public: void Insert (const lldb::TypeSP& type); - bool - InsertUnique (const lldb::TypeSP& type); - uint32_t GetSize() const; lldb::TypeSP GetTypeAtIndex(uint32_t idx); - typedef std::multimap collection; - typedef AdaptedIterable TypeIterable; + typedef std::vector collection; + typedef AdaptedIterable TypeIterable; TypeIterable Types () @@ -68,8 +65,6 @@ public: void ForEach (std::function const &callback); - bool - RemoveTypeWithUID (lldb::user_id_t uid); void RemoveMismatchedTypes (const char *qualified_typename, diff --git a/include/lldb/Symbol/TypeMap.h b/include/lldb/Symbol/TypeMap.h new file mode 100644 index 000000000000..4398acd789ae --- /dev/null +++ b/include/lldb/Symbol/TypeMap.h @@ -0,0 +1,98 @@ +//===-- TypeMap.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_TypeMap_h_ +#define liblldb_TypeMap_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Utility/Iterable.h" +#include +#include + +namespace lldb_private { + +class TypeMap +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeMap(); + + virtual + ~TypeMap(); + + void + Clear(); + + void + Dump(Stream *s, bool show_context); + + TypeMap + FindTypes(const ConstString &name); + + void + Insert (const lldb::TypeSP& type); + + bool + Empty() const; + + bool + InsertUnique (const lldb::TypeSP& type); + + uint32_t + GetSize() const; + + lldb::TypeSP + GetTypeAtIndex(uint32_t idx); + + typedef std::multimap collection; + typedef AdaptedIterable TypeIterable; + + TypeIterable + Types () + { + return TypeIterable(m_types); + } + + void + ForEach (std::function const &callback) const; + + void + ForEach (std::function const &callback); + + bool + Remove (const lldb::TypeSP &type_sp); + + void + RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match); + + void + RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + lldb::TypeClass type_class, + bool exact_match); + + void + RemoveMismatchedTypes (lldb::TypeClass type_class); + +private: + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_types; + + DISALLOW_COPY_AND_ASSIGN (TypeMap); +}; + +} // namespace lldb_private + +#endif // liblldb_TypeMap_h_ diff --git a/include/lldb/Symbol/TypeSystem.h b/include/lldb/Symbol/TypeSystem.h new file mode 100644 index 000000000000..d367bcdc0b14 --- /dev/null +++ b/include/lldb/Symbol/TypeSystem.h @@ -0,0 +1,604 @@ +//===-- TypeSystem.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_TypeSystem_h_ +#define liblldb_TypeSystem_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/ADT/APSInt.h" +#include "llvm/Support/Casting.h" + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Expression/Expression.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" + +class DWARFDIE; +class DWARFASTParser; + +namespace lldb_private { + +//---------------------------------------------------------------------- +// Interface for representing the Type Systems in different languages. +//---------------------------------------------------------------------- +class TypeSystem : public PluginInterface +{ +public: + //---------------------------------------------------------------------- + // Intrusive type system that allows us to use llvm casting. + // + // To add a new type system: + // + // 1 - Add a new enumeration for llvm casting below for your TypeSystem + // subclass, here we will use eKindFoo + // + // 2 - Your TypeSystem subclass will inherit from TypeSystem and needs + // to implement a static classof() function that returns your + // enumeration: + // + // class Foo : public lldb_private::TypeSystem + // { + // static bool classof(const TypeSystem *ts) + // { + // return ts->getKind() == TypeSystem::eKindFoo; + // } + // }; + // + // 3 - Contruct your TypeSystem subclass with the enumeration from below + // + // Foo() : + // TypeSystem(TypeSystem::eKindFoo), + // ... + // { + // } + // + // Then you can use the llvm casting on any "TypeSystem *" to get an + // instance of your subclass. + //---------------------------------------------------------------------- + enum LLVMCastKind { + eKindClang, + eKindSwift, + eKindGo, + kNumKinds + }; + + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + TypeSystem(LLVMCastKind kind); + + ~TypeSystem() override; + + LLVMCastKind getKind() const { return m_kind; } + + static lldb::TypeSystemSP + CreateInstance (lldb::LanguageType language, Module *module); + + static lldb::TypeSystemSP + CreateInstance (lldb::LanguageType language, Target *target); + + virtual DWARFASTParser * + GetDWARFParser () + { + return nullptr; + } + + virtual SymbolFile * + GetSymbolFile () const + { + return m_sym_file; + } + + // Returns true if the symbol file changed during the set accessor. + virtual void + SetSymbolFile (SymbolFile *sym_file) + { + m_sym_file = sym_file; + } + + //---------------------------------------------------------------------- + // CompilerDecl functions + //---------------------------------------------------------------------- + virtual ConstString + DeclGetName (void *opaque_decl) = 0; + + virtual ConstString + DeclGetMangledName (void *opaque_decl); + + virtual lldb::VariableSP + DeclGetVariable (void *opaque_decl) = 0; + + virtual void + DeclLinkToObject (void *opaque_decl, std::shared_ptr object) = 0; + + virtual CompilerDeclContext + DeclGetDeclContext (void *opaque_decl); + + virtual CompilerType + DeclGetFunctionReturnType(void *opaque_decl); + + virtual size_t + DeclGetFunctionNumArguments(void *opaque_decl); + + virtual CompilerType + DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx); + + //---------------------------------------------------------------------- + // CompilerDeclContext functions + //---------------------------------------------------------------------- + + virtual std::vector + DeclContextFindDeclByName (void *opaque_decl_ctx, ConstString name); + + virtual bool + DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) = 0; + + virtual ConstString + DeclContextGetName (void *opaque_decl_ctx) = 0; + + virtual bool + DeclContextIsClassMethod (void *opaque_decl_ctx, + lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, + ConstString *language_object_name_ptr) = 0; + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + virtual bool + IsArrayType (lldb::opaque_compiler_type_t type, + CompilerType *element_type, + uint64_t *size, + bool *is_incomplete) = 0; + + virtual bool + IsAggregateType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsAnonymousType (lldb::opaque_compiler_type_t type); + + virtual bool + IsCharType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsCompleteType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsDefined(lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) = 0; + + virtual bool + IsFunctionType (lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) = 0; + + virtual size_t + GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index) = 0; + + virtual bool + IsFunctionPointerType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) = 0; + + virtual bool + IsPossibleDynamicType (lldb::opaque_compiler_type_t type, + CompilerType *target_type, // Can pass NULL + bool check_cplusplus, + bool check_objc) = 0; + + virtual bool + IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) = 0; + + virtual bool + IsScalarType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsVoidType (lldb::opaque_compiler_type_t type) = 0; + + // TypeSystems can support more than one language + virtual bool + SupportsLanguage (lldb::LanguageType language) = 0; + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + virtual bool + GetCompleteType (lldb::opaque_compiler_type_t type) = 0; + + //---------------------------------------------------------------------- + // AST related queries + //---------------------------------------------------------------------- + + virtual uint32_t + GetPointerByteSize () = 0; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + virtual ConstString + GetTypeName (lldb::opaque_compiler_type_t type) = 0; + + virtual uint32_t + GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) = 0; + + virtual lldb::LanguageType + GetMinimumLanguage (lldb::opaque_compiler_type_t type) = 0; + + virtual lldb::TypeClass + GetTypeClass (lldb::opaque_compiler_type_t type) = 0; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + virtual CompilerType + GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride) = 0; + + virtual CompilerType + GetCanonicalType (lldb::opaque_compiler_type_t type) = 0; + + // 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. + virtual int + GetFunctionArgumentCount (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx) = 0; + + virtual CompilerType + GetFunctionReturnType (lldb::opaque_compiler_type_t type) = 0; + + virtual size_t + GetNumMemberFunctions (lldb::opaque_compiler_type_t type) = 0; + + virtual TypeMemberFunctionImpl + GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx) = 0; + + virtual CompilerType + GetPointeeType (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetPointerType (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetLValueReferenceType (lldb::opaque_compiler_type_t type); + + virtual CompilerType + GetRValueReferenceType (lldb::opaque_compiler_type_t type); + + virtual CompilerType + AddConstModifier (lldb::opaque_compiler_type_t type); + + virtual CompilerType + AddVolatileModifier (lldb::opaque_compiler_type_t type); + + virtual CompilerType + AddRestrictModifier (lldb::opaque_compiler_type_t type); + + virtual CompilerType + CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx); + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + virtual uint64_t + GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0; + + virtual lldb::Encoding + GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count) = 0; + + 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; + + virtual CompilerType + GetBuiltinTypeByName (const ConstString &name); + + virtual lldb::BasicType + GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type) = 0; + + virtual void + ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function const &callback) + { + } + + virtual uint32_t + GetNumFields (lldb::opaque_compiler_type_t type) = 0; + + virtual 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) = 0; + + virtual uint32_t + GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type) = 0; + + virtual uint32_t + GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type, + size_t idx, + uint32_t *bit_offset_ptr) = 0; + + virtual CompilerType + GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, + size_t idx, + uint32_t *bit_offset_ptr) = 0; + + virtual 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) = 0; + + // Lookup a child given a name. This function will match base class names + // and member member names in "clang_type" only, not descendants. + virtual uint32_t + GetIndexOfChildWithName (lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) = 0; + + // 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> + // so we catch all names that match a given child name, not just the first. + virtual size_t + GetIndexOfChildMemberWithName (lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes, + std::vector& child_indexes) = 0; + + virtual size_t + GetNumTemplateArguments (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetTemplateArgument (lldb::opaque_compiler_type_t type, + size_t idx, + lldb::TemplateArgumentKind &kind) = 0; + + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + + virtual 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) = 0; + + virtual 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) = 0; + + virtual void + DumpTypeDescription (lldb::opaque_compiler_type_t type) = 0; // Dump to stdout + + virtual void + DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) = 0; + + //---------------------------------------------------------------------- + // TODO: These methods appear unused. Should they be removed? + //---------------------------------------------------------------------- + + virtual bool + IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) = 0; + + virtual 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) = 0; + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + virtual size_t + ConvertStringToFloatValue (lldb::opaque_compiler_type_t type, + const char *s, + uint8_t *dst, + size_t dst_size) = 0; + + //---------------------------------------------------------------------- + // TODO: Determine if these methods should move to ClangASTContext. + //---------------------------------------------------------------------- + + virtual bool + IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) = 0; + + virtual unsigned + GetTypeQualifiers(lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) = 0; + + virtual size_t + GetTypeBitAlign (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetBasicTypeFromAST (lldb::BasicType basic_type) = 0; + + virtual CompilerType + GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, + size_t bit_size) = 0; + + virtual bool + IsBeingDefined (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsConst(lldb::opaque_compiler_type_t type) = 0; + + virtual uint32_t + IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr) = 0; + + virtual bool + IsPolymorphicClass (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsTypedefType (lldb::opaque_compiler_type_t type) = 0; + + // If the current object represents a typedef type, get the underlying type + virtual CompilerType + GetTypedefedType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsVectorType (lldb::opaque_compiler_type_t type, + CompilerType *element_type, + uint64_t *size) = 0; + + virtual CompilerType + GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type) = 0; + + virtual CompilerType + GetNonReferenceType (lldb::opaque_compiler_type_t type) = 0; + + virtual bool + IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue) = 0; + + virtual bool + ShouldTreatScalarValueAsAddress (lldb::opaque_compiler_type_t type) + { + return IsPointerOrReferenceType(type, nullptr); + } + + virtual UserExpression * + GetUserExpression (const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options) + { + return nullptr; + } + + virtual FunctionCaller * + GetFunctionCaller (const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name) + { + return nullptr; + } + + virtual UtilityFunction * + GetUtilityFunction(const char *text, const char *name) + { + return nullptr; + } + + virtual PersistentExpressionState * + GetPersistentExpressionState() + { + return nullptr; + } + + virtual CompilerType + GetTypeForFormatters (void* type); + + virtual LazyBool + ShouldPrintAsOneLiner (void* type, ValueObject* valobj); + + // Type systems can have types that are placeholder types, which are meant to indicate + // the presence of a type, but offer no actual information about said types, and leave + // the burden of actually figuring type information out to dynamic type resolution. For instance + // a language with a generics system, can use placeholder types to indicate "type argument goes here", + // without promising uniqueness of the placeholder, nor attaching any actually idenfiable information + // to said placeholder. This API allows type systems to tell LLDB when such a type has been encountered + // In response, the debugger can react by not using this type as a cache entry in any type-specific way + // For instance, LLDB will currently not cache any formatters that are discovered on such a type as + // attributable to the meaningless type itself, instead preferring to use the dynamic type + virtual bool + IsMeaninglessWithoutDynamicResolution (void* type); + +protected: + const LLVMCastKind m_kind; // Support for llvm casting + SymbolFile *m_sym_file; + +}; + + class TypeSystemMap + { + public: + TypeSystemMap (); + ~TypeSystemMap(); + + void + Clear (); + + // Iterate through all of the type systems that are created. Return true + // from callback to keep iterating, false to stop iterating. + void + ForEach (std::function const &callback); + + TypeSystem * + GetTypeSystemForLanguage (lldb::LanguageType language, Module *module, bool can_create); + + TypeSystem * + GetTypeSystemForLanguage (lldb::LanguageType language, Target *target, bool can_create); + + protected: + typedef std::map collection; + mutable Mutex m_mutex; ///< A mutex to keep this object happy in multi-threaded environments. + collection m_map; + }; + +} // namespace lldb_private + +#endif // liblldb_TypeSystem_h_ diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h index bfc008a5b6bc..71100138413d 100644 --- a/include/lldb/Symbol/UnwindPlan.h +++ b/include/lldb/Symbol/UnwindPlan.h @@ -1,14 +1,28 @@ +//===-- UnwindPlan.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_UnwindPlan_h #define liblldb_UnwindPlan_h +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/Stream.h" #include "lldb/Core/ConstString.h" -#include -#include - namespace lldb_private { // The UnwindPlan object specifies how to unwind out of a function - where @@ -38,13 +52,11 @@ namespace lldb_private { class UnwindPlan { public: - class Row { public: class RegisterLocation { public: - enum RestoreType { unspecified, // not specified, we may be able to assume this @@ -187,7 +199,7 @@ public: } else { - *opcodes = NULL; + *opcodes = nullptr; len = 0; } } @@ -203,7 +215,7 @@ public: { if (m_type == atDWARFExpression || m_type == isDWARFExpression) return m_location.expr.opcodes; - return NULL; + return nullptr; } int @@ -240,7 +252,6 @@ public: class CFAValue { public: - enum ValueType { unspecified, // not specified @@ -361,7 +372,7 @@ public: } else { - *opcodes = NULL; + *opcodes = nullptr; len = 0; } } @@ -371,7 +382,7 @@ public: { if (m_type == isDWARFExpression) return m_value.expr.opcodes; - return NULL; + return nullptr; } int @@ -488,7 +499,6 @@ public: }; // class Row public: - typedef std::shared_ptr RowSP; UnwindPlan (lldb::RegisterKind reg_kind) : @@ -520,9 +530,7 @@ public: m_row_list.emplace_back (new Row (*row_sp)); } - ~UnwindPlan () - { - } + ~UnwindPlan() = default; void Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const; @@ -676,8 +684,6 @@ public: } private: - - typedef std::vector collection; collection m_row_list; AddressRange m_plan_valid_address_range; @@ -697,4 +703,4 @@ private: } // namespace lldb_private -#endif //liblldb_UnwindPlan_h +#endif // liblldb_UnwindPlan_h diff --git a/include/lldb/Symbol/UnwindTable.h b/include/lldb/Symbol/UnwindTable.h index 38d3ff6dd3c9..f69e4660de24 100644 --- a/include/lldb/Symbol/UnwindTable.h +++ b/include/lldb/Symbol/UnwindTable.h @@ -34,6 +34,9 @@ public: lldb_private::CompactUnwindInfo * GetCompactUnwindInfo (); + ArmUnwindInfo * + GetArmUnwindInfo (); + lldb::FuncUnwindersSP GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); @@ -65,9 +68,10 @@ private: bool m_initialized; // delay some initialization until ObjectFile is set up Mutex m_mutex; - DWARFCallFrameInfo* m_eh_frame; - CompactUnwindInfo *m_compact_unwind; - + std::unique_ptr m_eh_frame_up; + std::unique_ptr m_compact_unwind_up; + std::unique_ptr m_arm_unwind_up; + DISALLOW_COPY_AND_ASSIGN (UnwindTable); }; diff --git a/include/lldb/Symbol/Variable.h b/include/lldb/Symbol/Variable.h index 8d413cac3d7d..1cac5d0c5649 100644 --- a/include/lldb/Symbol/Variable.h +++ b/include/lldb/Symbol/Variable.h @@ -1,4 +1,5 @@ -//===-- Variable.h ----------------------------------------------*- C++ -*-===// +//===-- Variable.h ----------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,6 +11,7 @@ #ifndef liblldb_Variable_h_ #define liblldb_Variable_h_ +#include #include #include "lldb/lldb-private.h" @@ -21,7 +23,8 @@ namespace lldb_private { -class Variable : public UserID +class Variable : public UserID, + public std::enable_shared_from_this { public: //------------------------------------------------------------------ @@ -36,7 +39,8 @@ public: Declaration* decl, const DWARFExpression& location, bool external, - bool artificial); + bool artificial, + bool static_member = false); virtual ~Variable(); @@ -58,6 +62,9 @@ public: ConstString GetName() const; + ConstString + GetUnqualifiedName() const; + SymbolContextScope * GetSymbolContextScope() const { @@ -99,6 +106,11 @@ public: return m_artificial; } + bool IsStaticMember() const + { + return m_static_member; + } + DWARFExpression & LocationExpression() { @@ -161,6 +173,11 @@ public: StringList &matches, bool &word_complete); + CompilerDeclContext + GetDeclContext (); + + CompilerDecl + GetDecl (); protected: ConstString m_name; // The basename of the variable (no namespaces) Mangled m_mangled; // The mangled name of the variable @@ -171,7 +188,8 @@ protected: DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() uint8_t m_external:1, // Visible outside the containing compile unit? m_artificial:1, // Non-zero if the variable is not explicitly declared in source - m_loc_is_const_data:1; // The m_location expression contains the constant variable value data, not a DWARF location + m_loc_is_const_data:1, // The m_location expression contains the constant variable value data, not a DWARF location + m_static_member:1; // Non-zero if variable is static member of a class or struct. private: Variable(const Variable& rhs); Variable& operator=(const Variable& rhs); diff --git a/include/lldb/Symbol/VariableList.h b/include/lldb/Symbol/VariableList.h index 5f8f2a225650..1c1d5dfefb9e 100644 --- a/include/lldb/Symbol/VariableList.h +++ b/include/lldb/Symbol/VariableList.h @@ -48,10 +48,10 @@ public: RemoveVariableAtIndex (size_t idx); lldb::VariableSP - FindVariable (const ConstString& name); + FindVariable (const ConstString& name, bool include_static_members = true); lldb::VariableSP - FindVariable (const ConstString& name, lldb::ValueType value_type); + FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members = true); uint32_t FindVariableIndex (const lldb::VariableSP &var_sp); diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h index 89d4f6bdba6c..94826d173500 100644 --- a/include/lldb/Target/ABI.h +++ b/include/lldb/Target/ABI.h @@ -44,8 +44,7 @@ public: std::unique_ptr data_ap; /* host data pointer */ }; - virtual - ~ABI(); + ~ABI() override; virtual size_t GetRedZoneSize () const = 0; @@ -78,7 +77,7 @@ public: lldb::ValueObjectSP GetReturnValueObject (Thread &thread, - ClangASTType &type, + CompilerType &type, bool persistent = true) const; // specialized to work with llvm IR types @@ -95,7 +94,7 @@ protected: // This is the method the ABI will call to actually calculate the return value. // Don't put it in a persistent value object, that will be done by the ABI::GetReturnValueObject. virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type) const = 0; + GetReturnValueObjectImpl (Thread &thread, CompilerType &ast_type) const = 0; // specialized to work with llvm IR types virtual lldb::ValueObjectSP @@ -148,14 +147,17 @@ public: FindPlugin (const ArchSpec &arch); protected: + //------------------------------------------------------------------ // Classes that inherit from ABI can see and modify these //------------------------------------------------------------------ ABI(); + private: + DISALLOW_COPY_AND_ASSIGN (ABI); }; } // namespace lldb_private -#endif // liblldb_ABI_h_ +#endif // liblldb_ABI_h_ diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h index 3e51453566b3..ac537d0ad1e5 100644 --- a/include/lldb/Target/CPPLanguageRuntime.h +++ b/include/lldb/Target/CPPLanguageRuntime.h @@ -25,100 +25,10 @@ class CPPLanguageRuntime : public LanguageRuntime { public: + ~CPPLanguageRuntime() override; - class MethodName - { - public: - enum Type - { - eTypeInvalid, - eTypeUnknownMethod, - eTypeClassMethod, - eTypeInstanceMethod - }; - - MethodName () : - m_full(), - m_basename(), - m_context(), - m_arguments(), - m_qualifiers(), - m_type (eTypeInvalid), - m_parsed (false), - m_parse_error (false) - { - } - - MethodName (const ConstString &s) : - m_full(s), - m_basename(), - m_context(), - m_arguments(), - m_qualifiers(), - m_type (eTypeInvalid), - m_parsed (false), - m_parse_error (false) - { - } - - void - Clear(); - - bool - IsValid () - { - if (!m_parsed) - Parse(); - if (m_parse_error) - return false; - if (m_type == eTypeInvalid) - return false; - return (bool)m_full; - } - - Type - GetType () const - { - return m_type; - } - - const ConstString & - GetFullName () const - { - return m_full; - } - - llvm::StringRef - GetBasename (); - - llvm::StringRef - GetContext (); - - llvm::StringRef - GetArguments (); - - llvm::StringRef - GetQualifiers (); - - protected: - void - Parse(); - - ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const" - llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex" - llvm::StringRef m_context; // Decl context: "lldb::SBTarget" - llvm::StringRef m_arguments; // Arguments: "(unsigned int)" - llvm::StringRef m_qualifiers; // Qualifiers: "const" - Type m_type; - bool m_parsed; - bool m_parse_error; - }; - - virtual - ~CPPLanguageRuntime(); - - virtual lldb::LanguageType - GetLanguageType () const + lldb::LanguageType + GetLanguageType() const override { return lldb::eLanguageTypeC_plus_plus; } @@ -126,45 +36,27 @@ public: virtual bool IsVTableName (const char *name) = 0; - virtual bool - GetObjectDescription (Stream &str, ValueObject &object); - - virtual bool - GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope); + bool + GetObjectDescription(Stream &str, ValueObject &object) override; - static bool - IsCPPMangledName(const char *name); - - // Extract C++ context and identifier from a string using heuristic matching (as opposed to - // CPPLanguageRuntime::MethodName which has to have a fully qualified C++ name with parens and arguments. - // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true, - // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively. - // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false - // and identifier and context will be unchanged. - - static bool - ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier); + bool + GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override; - // in some cases, compilers will output different names for one same type. when that happens, it might be impossible - // to construct SBType objects for a valid type, because the name that is available is not the same as the name that - // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names - // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended - // to ObjC or other languages if necessary - static uint32_t - FindEquivalentNames(ConstString type_name, std::vector& equivalents); - virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector &alternates) = 0; protected: + //------------------------------------------------------------------ // Classes that inherit from CPPLanguageRuntime can see and modify these //------------------------------------------------------------------ CPPLanguageRuntime(Process *process); + private: + DISALLOW_COPY_AND_ASSIGN (CPPLanguageRuntime); }; } // namespace lldb_private -#endif // liblldb_CPPLanguageRuntime_h_ +#endif // liblldb_CPPLanguageRuntime_h_ diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h index 6652a5ec144f..5eada0342a21 100644 --- a/include/lldb/Target/DynamicLoader.h +++ b/include/lldb/Target/DynamicLoader.h @@ -71,8 +71,7 @@ public: /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. //------------------------------------------------------------------ - virtual - ~DynamicLoader (); + ~DynamicLoader() override; //------------------------------------------------------------------ /// Called after attaching a process. @@ -264,12 +263,14 @@ protected: virtual void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset); // Utility method so base classes can share implementation of UpdateLoadedSections void UpdateLoadedSectionsCommon(lldb::ModuleSP module, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset); /// Removes the loaded sections from the target in @p module. /// @@ -283,8 +284,11 @@ protected: /// Locates or creates a module given by @p file and updates/loads the /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); + virtual lldb::ModuleSP + LoadModuleAtAddress(const lldb_private::FileSpec &file, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset); const lldb_private::SectionList * GetSectionListFromModule(const lldb::ModuleSP module) const; @@ -303,11 +307,12 @@ protected: // Member variables. //------------------------------------------------------------------ Process* m_process; ///< The process that this dynamic loader plug-in is tracking. + private: - DISALLOW_COPY_AND_ASSIGN (DynamicLoader); + DISALLOW_COPY_AND_ASSIGN (DynamicLoader); }; } // namespace lldb_private -#endif // liblldb_DynamicLoader_h_ +#endif // liblldb_DynamicLoader_h_ diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h index 50f2beaf949b..cdf55e3b744c 100644 --- a/include/lldb/Target/ExecutionContext.h +++ b/include/lldb/Target/ExecutionContext.h @@ -5,6 +5,21 @@ // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ExecutionContext_h_ +#define liblldb_ExecutionContext_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/StackID.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + //===----------------------------------------------------------------------===// /// Execution context objects refer to objects in the execution of the /// program that is being debugged. The consist of one or more of the @@ -30,17 +45,6 @@ /// to a wide variety of functions that require execution contexts. //===----------------------------------------------------------------------===// - - -#ifndef liblldb_ExecutionContext_h_ -#define liblldb_ExecutionContext_h_ - -#include "lldb/lldb-private.h" -#include "lldb/Target/StackID.h" -#include "lldb/Host/Mutex.h" - -namespace lldb_private { - //---------------------------------------------------------------------- /// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h" /// @brief A class that holds a weak reference to an execution context. @@ -86,7 +90,7 @@ public: ExecutionContextRef (const ExecutionContextRef &rhs); //------------------------------------------------------------------ - /// Construct using an ExecutionContext object that might be NULL. + /// Construct using an ExecutionContext object that might be nullptr. /// /// If \a exe_ctx_ptr is valid, then make weak references to any /// valid objects in the ExecutionContext, otherwise no weak @@ -101,22 +105,6 @@ public: //------------------------------------------------------------------ ExecutionContextRef (const ExecutionContext &exe_ctx); - //------------------------------------------------------------------ - /// Assignment operator - /// - /// Copy all weak references in \a rhs. - //------------------------------------------------------------------ - ExecutionContextRef & - operator =(const ExecutionContextRef &rhs); - - //------------------------------------------------------------------ - /// Assignment operator from a ExecutionContext - /// - /// Make weak references to any strongly referenced objects in \a exe_ctx. - //------------------------------------------------------------------ - ExecutionContextRef & - operator =(const ExecutionContext &exe_ctx); - //------------------------------------------------------------------ /// Construct using the target and all the selected items inside of it /// (the process and its selected thread, and the thread's selected @@ -154,10 +142,27 @@ public: ExecutionContextRef (ExecutionContextScope &exe_scope); ~ExecutionContextRef(); + + //------------------------------------------------------------------ + /// Assignment operator + /// + /// Copy all weak references in \a rhs. + //------------------------------------------------------------------ + ExecutionContextRef & + operator =(const ExecutionContextRef &rhs); + + //------------------------------------------------------------------ + /// Assignment operator from a ExecutionContext + /// + /// Make weak references to any strongly referenced objects in \a exe_ctx. + //------------------------------------------------------------------ + ExecutionContextRef & + operator =(const ExecutionContext &exe_ctx); + //------------------------------------------------------------------ /// Clear the object's state. /// - /// Sets the process and thread to NULL, and the frame index to an + /// Sets the process and thread to nullptr, and the frame index to an /// invalid value. //------------------------------------------------------------------ void @@ -394,6 +399,7 @@ public: ExecutionContext (const lldb::ProcessSP &process_sp); ExecutionContext (const lldb::ThreadSP &thread_sp); ExecutionContext (const lldb::StackFrameSP &frame_sp); + //------------------------------------------------------------------ // Create execution contexts from weak pointers //------------------------------------------------------------------ @@ -413,16 +419,6 @@ public: //------------------------------------------------------------------ ExecutionContext (ExecutionContextScope *exe_scope); ExecutionContext (ExecutionContextScope &exe_scope); - - - ExecutionContext & - operator =(const ExecutionContext &rhs); - - bool - operator ==(const ExecutionContext &rhs) const; - - bool - operator !=(const ExecutionContext &rhs) const; //------------------------------------------------------------------ /// Construct with process, thread, and frame index. @@ -438,16 +434,26 @@ public: /// @param[in] frame /// The frame index for this execution context. //------------------------------------------------------------------ - ExecutionContext (Process* process, - Thread *thread = NULL, - StackFrame * frame = NULL); + ExecutionContext(Process* process, + Thread *thread = nullptr, + StackFrame * frame = nullptr); ~ExecutionContext(); + + ExecutionContext & + operator =(const ExecutionContext &rhs); + + bool + operator ==(const ExecutionContext &rhs) const; + + bool + operator !=(const ExecutionContext &rhs) const; + //------------------------------------------------------------------ /// Clear the object's state. /// - /// Sets the process and thread to NULL, and the frame index to an + /// Sets the process and thread to nullptr, and the frame index to an /// invalid value. //------------------------------------------------------------------ void @@ -468,10 +474,10 @@ public: //------------------------------------------------------------------ /// Returns a pointer to the target object. /// - /// The returned pointer might be NULL. Calling HasTargetScope(), + /// The returned pointer might be nullptr. Calling HasTargetScope(), /// HasProcessScope(), HasThreadScope(), or HasFrameScope() /// can help to pre-validate this pointer so that this accessor can - /// freely be used without having to check for NULL each time. + /// freely be used without having to check for nullptr each time. /// /// @see ExecutionContext::HasTargetScope() const /// @see ExecutionContext::HasProcessScope() const @@ -484,10 +490,10 @@ public: //------------------------------------------------------------------ /// Returns a pointer to the process object. /// - /// The returned pointer might be NULL. Calling HasProcessScope(), + /// The returned pointer might be nullptr. Calling HasProcessScope(), /// HasThreadScope(), or HasFrameScope() can help to pre-validate /// this pointer so that this accessor can freely be used without - /// having to check for NULL each time. + /// having to check for nullptr each time. /// /// @see ExecutionContext::HasProcessScope() const /// @see ExecutionContext::HasThreadScope() const @@ -499,10 +505,10 @@ public: //------------------------------------------------------------------ /// Returns a pointer to the thread object. /// - /// The returned pointer might be NULL. Calling HasThreadScope() or + /// The returned pointer might be nullptr. Calling HasThreadScope() or /// HasFrameScope() can help to pre-validate this pointer so that /// this accessor can freely be used without having to check for - /// NULL each time. + /// nullptr each time. /// /// @see ExecutionContext::HasThreadScope() const /// @see ExecutionContext::HasFrameScope() const @@ -516,9 +522,9 @@ public: //------------------------------------------------------------------ /// Returns a pointer to the frame object. /// - /// The returned pointer might be NULL. Calling HasFrameScope(), + /// The returned pointer might be nullptr. Calling HasFrameScope(), /// can help to pre-validate this pointer so that this accessor can - /// freely be used without having to check for NULL each time. + /// freely be used without having to check for nullptr each time. /// /// @see ExecutionContext::HasFrameScope() const //------------------------------------------------------------------ @@ -776,6 +782,7 @@ protected: lldb::ThreadSP m_thread_sp; ///< The thread that owns the frame lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread. }; + } // namespace lldb_private -#endif // liblldb_ExecutionContext_h_ +#endif // liblldb_ExecutionContext_h_ diff --git a/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/include/lldb/Target/InstrumentationRuntimeStopInfo.h index 624267ce8221..df1b937e6e26 100644 --- a/include/lldb/Target/InstrumentationRuntimeStopInfo.h +++ b/include/lldb/Target/InstrumentationRuntimeStopInfo.h @@ -25,18 +25,24 @@ class InstrumentationRuntimeStopInfo : public StopInfo { public: - virtual ~InstrumentationRuntimeStopInfo() + ~InstrumentationRuntimeStopInfo() override { } - virtual lldb::StopReason - GetStopReason () const + lldb::StopReason + GetStopReason() const override { return lldb::eStopReasonInstrumentation; } - virtual const char * - GetDescription (); + const char * + GetDescription() override; + + bool + DoShouldNotify(Event *event_ptr) override + { + return true; + } static lldb::StopInfoSP CreateStopReasonWithInstrumentationData (Thread &thread, std::string description, StructuredData::ObjectSP additional_data); @@ -44,9 +50,8 @@ public: private: InstrumentationRuntimeStopInfo(Thread &thread, std::string description, StructuredData::ObjectSP additional_data); - }; } // namespace lldb_private -#endif // liblldb_InstrumentationRuntimeStopInfo_h_ +#endif // liblldb_InstrumentationRuntimeStopInfo_h_ diff --git a/include/lldb/Target/JITLoader.h b/include/lldb/Target/JITLoader.h index c15ae5a876f1..8a2d6828db2f 100644 --- a/include/lldb/Target/JITLoader.h +++ b/include/lldb/Target/JITLoader.h @@ -50,8 +50,7 @@ public: //------------------------------------------------------------------ JITLoader (Process *process); - virtual - ~JITLoader (); + ~JITLoader() override; //------------------------------------------------------------------ /// Called after attaching a process. diff --git a/include/lldb/Target/Language.h b/include/lldb/Target/Language.h new file mode 100644 index 000000000000..492425ec088b --- /dev/null +++ b/include/lldb/Target/Language.h @@ -0,0 +1,206 @@ +//===-- Language.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_Language_h_ +#define liblldb_Language_h_ + +// C Includes +// C++ Includes +#include +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/DataFormatters/DumpValueObjectOptions.h" +#include "lldb/DataFormatters/FormatClasses.h" +#include "lldb/DataFormatters/StringPrinter.h" + +namespace lldb_private { + +class Language : +public PluginInterface +{ +public: + class TypeScavenger + { + public: + class Result + { + public: + virtual bool + IsValid () = 0; + + virtual bool + DumpToStream (Stream& stream, + bool print_help_if_available) = 0; + + virtual ~Result() = default; + }; + + typedef std::set> ResultSet; + + virtual ~TypeScavenger () = default; + + size_t + Find (ExecutionContextScope *exe_scope, + const char *key, + ResultSet &results, + bool append = true); + + protected: + TypeScavenger () = default; + + virtual bool + Find_Impl (ExecutionContextScope *exe_scope, + const char *key, + ResultSet &results) = 0; + }; + + enum class FunctionNameRepresentation + { + eName, + eNameWithArgs, + eNameWithNoArgs + }; + + ~Language() override; + + static Language* + FindPlugin (lldb::LanguageType language); + + // return false from callback to stop iterating + static void + ForEach (std::function callback); + + virtual lldb::LanguageType + GetLanguageType () const = 0; + + virtual bool + IsTopLevelFunction (Function& function); + + virtual lldb::TypeCategoryImplSP + GetFormatters (); + + virtual HardcodedFormatters::HardcodedFormatFinder + GetHardcodedFormats (); + + virtual HardcodedFormatters::HardcodedSummaryFinder + GetHardcodedSummaries (); + + virtual HardcodedFormatters::HardcodedSyntheticFinder + GetHardcodedSynthetics (); + + virtual HardcodedFormatters::HardcodedValidatorFinder + GetHardcodedValidators (); + + virtual std::vector + GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic); + + virtual lldb_private::formatters::StringPrinter::EscapingHelper + GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType); + + virtual std::unique_ptr + GetTypeScavenger (); + + // if an individual data formatter can apply to several types and cross a language boundary + // it makes sense for individual languages to want to customize the printing of values of that + // type by appending proper prefix/suffix information in language-specific ways + virtual bool + GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint, + std::string& prefix, std::string& suffix); + + // if a language has a custom format for printing variable declarations that it wants LLDB to honor + // it should return an appropriate closure here + virtual DumpValueObjectOptions::DeclPrintingHelper + GetDeclPrintingHelper (); + + virtual LazyBool + IsLogicalTrue (ValueObject& valobj, + Error& error); + + // for a ValueObject of some "reference type", if the value points to the + // nil/null object, this method returns true + virtual bool + IsNilReference (ValueObject& valobj); + + // for a ValueObject of some "reference type", if the language provides a technique + // to decide whether the reference has ever been assigned to some object, this method + // will return true if such detection is possible, and if the reference has never been assigned + virtual bool + IsUninitializedReference (ValueObject& valobj); + + virtual bool + GetFunctionDisplayName (const SymbolContext *sc, + const ExecutionContext *exe_ctx, + FunctionNameRepresentation representation, + Stream& s); + + virtual void + GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s); + + static void + GetDefaultExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s); + + // These are accessors for general information about the Languages lldb knows about: + + static lldb::LanguageType + GetLanguageTypeFromString (const char *string); + + static const char * + GetNameForLanguageType (lldb::LanguageType language); + + static void + PrintAllLanguages (Stream &s, const char *prefix, const char *suffix); + + // return false from callback to stop iterating + static void + ForAllLanguages (std::function callback); + + static bool + LanguageIsCPlusPlus (lldb::LanguageType language); + + static bool + LanguageIsObjC (lldb::LanguageType language); + + static bool + LanguageIsC (lldb::LanguageType language); + + static bool + LanguageIsPascal (lldb::LanguageType language); + + // return the primary language, so if LanguageIsC(l), return eLanguageTypeC, etc. + static lldb::LanguageType + GetPrimaryLanguage (lldb::LanguageType language); + + static void + GetLanguagesSupportingTypeSystems (std::set &languages, + std::set &languages_for_expressions); + + static void + GetLanguagesSupportingREPLs (std::set &languages); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from Language can see and modify these + //------------------------------------------------------------------ + + Language(); +private: + + DISALLOW_COPY_AND_ASSIGN (Language); +}; + +} // namespace lldb_private + +#endif // liblldb_Language_h_ diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h index d8e5ada6c96f..686ec5ea3479 100644 --- a/include/lldb/Target/LanguageRuntime.h +++ b/include/lldb/Target/LanguageRuntime.h @@ -29,8 +29,8 @@ class LanguageRuntime : public PluginInterface { public: - virtual - ~LanguageRuntime(); + + ~LanguageRuntime() override; static LanguageRuntime* FindPlugin (Process *process, lldb::LanguageType language); @@ -52,12 +52,31 @@ public: GetDynamicTypeAndAddress (ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, - Address &address) = 0; + Address &address, + Value::ValueType &value_type) = 0; + + // This call should return a CompilerType given a generic type name + // and an ExecutionContextScope in which one can actually fetch + // any specialization information required. + virtual CompilerType + GetConcreteType (ExecutionContextScope *exe_scope, + ConstString abstract_type_name) + { + return CompilerType(); + } // This should be a fast test to determine whether it is likely that this value would // have a dynamic type. virtual bool CouldHaveDynamicValue (ValueObject &in_value) = 0; + + // The contract for GetDynamicTypeAndAddress() is to return a "bare-bones" dynamic type + // For instance, given a Base* pointer, GetDynamicTypeAndAddress() will return the type of + // Derived, not Derived*. The job of this API is to correct this misalignment between the + // static type and the discovered dynamic type + virtual TypeAndOrName + FixUpDynamicType (const TypeAndOrName& type_and_or_name, + ValueObject& static_value) = 0; virtual void SetExceptionBreakpoints () @@ -92,24 +111,17 @@ public: CreateExceptionPrecondition (lldb::LanguageType language, bool catch_bp, bool throw_bp); - - static lldb::LanguageType - GetLanguageTypeFromString (const char *string); - - static const char * - GetNameForLanguageType (lldb::LanguageType language); - - static void - PrintAllLanguages (Stream &s, const char *prefix, const char *suffix); - - static bool - LanguageIsCPlusPlus (lldb::LanguageType language); - Process * GetProcess() { return m_process; } + + Target& + GetTargetRef() + { + return m_process->GetTarget(); + } virtual lldb::BreakpointResolverSP CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) = 0; @@ -118,7 +130,7 @@ public: CreateExceptionSearchFilter (); virtual bool - GetTypeBitSize (const ClangASTType& clang_type, + GetTypeBitSize (const CompilerType& compiler_type, uint64_t &size) { return false; @@ -133,7 +145,6 @@ public: virtual void ModulesDidLoad (const ModuleList &module_list) { - return; } protected: @@ -144,9 +155,10 @@ protected: LanguageRuntime(Process *process); Process *m_process; private: + DISALLOW_COPY_AND_ASSIGN (LanguageRuntime); }; } // namespace lldb_private -#endif // liblldb_LanguageRuntime_h_ +#endif // liblldb_LanguageRuntime_h_ diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h index 88874c767a1b..75f096fdedfe 100644 --- a/include/lldb/Target/ObjCLanguageRuntime.h +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -1,4 +1,4 @@ -//===-- ObjCLanguageRuntime.h ---------------------------------------------------*- C++ -*-===// +//===-- ObjCLanguageRuntime.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,14 +14,17 @@ // C++ Includes #include #include +#include #include // Other libraries and framework includes +#include "llvm/Support/Casting.h" + // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeDenseMap.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/DeclVendor.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/LanguageRuntime.h" @@ -30,115 +33,19 @@ class CommandObjectObjC_ClassTable_Dump; namespace lldb_private { -class ClangUtilityFunction; +class UtilityFunction; class ObjCLanguageRuntime : public LanguageRuntime { public: - class MethodName + enum class ObjCRuntimeVersions { - public: - enum Type - { - eTypeUnspecified, - eTypeClassMethod, - eTypeInstanceMethod - }; - - MethodName () : - m_full(), - m_class(), - m_category(), - m_selector(), - m_type (eTypeUnspecified), - m_category_is_valid (false) - { - } - - MethodName (const char *name, bool strict) : - m_full(), - m_class(), - m_category(), - m_selector(), - m_type (eTypeUnspecified), - m_category_is_valid (false) - { - SetName (name, strict); - } - - void - Clear(); - - bool - IsValid (bool strict) const - { - // If "strict" is true, the name must have everything specified including - // the leading "+" or "-" on the method name - if (strict && m_type == eTypeUnspecified) - return false; - // Other than that, m_full will only be filled in if the objective C - // name is valid. - return (bool)m_full; - } - - bool - HasCategory() - { - return (bool)GetCategory(); - } - - Type - GetType () const - { - return m_type; - } - - const ConstString & - GetFullName () const - { - return m_full; - } - - ConstString - GetFullNameWithoutCategory (bool empty_if_no_category); - - bool - SetName (const char *name, bool strict); - - const ConstString & - GetClassName (); - - const ConstString & - GetClassNameWithCategory (); - - const ConstString & - GetCategory (); - - const ConstString & - GetSelector (); - - // Get all possible names for a method. Examples: - // If name is "+[NSString(my_additions) myStringWithCString:]" - // names[0] => "+[NSString(my_additions) myStringWithCString:]" - // names[1] => "+[NSString myStringWithCString:]" - // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]" - // names[0] => "+[NSString(my_additions) myStringWithCString:]" - // names[1] => "-[NSString(my_additions) myStringWithCString:]" - // names[2] => "+[NSString myStringWithCString:]" - // names[3] => "-[NSString myStringWithCString:]" - size_t - GetFullNames (std::vector &names, bool append); - protected: - ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]" - ConstString m_class; // Class name: "NSString" - ConstString m_class_category; // Class with category: "NSString(my_additions)" - ConstString m_category; // Category: "my_additions" - ConstString m_selector; // Selector: "myStringWithCString:" - Type m_type; - bool m_category_is_valid; - + eObjC_VersionUnknown = 0, + eAppleObjC_V1 = 1, + eAppleObjC_V2 = 2 }; + typedef lldb::addr_t ObjCISA; class ClassDescriptor; @@ -150,7 +57,6 @@ public: class ClassDescriptor { public: - ClassDescriptor() : m_is_kvo (eLazyBoolCalculate), m_is_cf (eLazyBoolCalculate), @@ -159,10 +65,8 @@ public: } virtual - ~ClassDescriptor () - { - } - + ~ClassDescriptor() = default; + virtual ConstString GetClassName () = 0; @@ -203,12 +107,12 @@ public: virtual bool IsValid () = 0; - + virtual bool - GetTaggedPointerInfo (uint64_t* info_bits = NULL, - uint64_t* value_bits = NULL, - uint64_t* payload = NULL) = 0; - + GetTaggedPointerInfo(uint64_t* info_bits = nullptr, + uint64_t* value_bits = nullptr, + uint64_t* payload = nullptr) = 0; + virtual uint64_t GetInstanceSize () = 0; @@ -247,7 +151,7 @@ public: struct iVarDescriptor { ConstString m_name; - ClangASTType m_type; + CompilerType m_type; uint64_t m_size; int32_t m_offset; }; @@ -281,12 +185,12 @@ public: class EncodingToType { public: - virtual ClangASTType RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression); - virtual ClangASTType RealizeType (const char* name, bool for_expression); - - virtual ClangASTType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool for_expression) = 0; - virtual ~EncodingToType(); + + virtual CompilerType RealizeType (ClangASTContext& ast_ctx, const char* name, bool for_expression); + virtual CompilerType RealizeType (const char* name, bool for_expression); + + virtual CompilerType RealizeType (clang::ASTContext& ast_ctx, const char* name, bool for_expression) = 0; protected: std::unique_ptr m_scratch_ast_ctx_ap; @@ -297,10 +201,10 @@ public: public: ObjCExceptionPrecondition(); - virtual ~ObjCExceptionPrecondition() {} + ~ObjCExceptionPrecondition() override = default; bool EvaluatePrecondition(StoppointCallbackContext &context) override; - void DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) override; + void GetDescription(Stream &stream, lldb::DescriptionLevel level) override; Error ConfigurePrecondition(Args &args) override; protected: @@ -313,21 +217,24 @@ public: class TaggedPointerVendor { public: + virtual + ~TaggedPointerVendor() = default; + virtual bool IsPossibleTaggedPointer (lldb::addr_t ptr) = 0; virtual ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor (lldb::addr_t ptr) = 0; - - virtual - ~TaggedPointerVendor () { } + protected: - TaggedPointerVendor () = default; + TaggedPointerVendor() = default; private: DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendor); }; + ~ObjCLanguageRuntime() override; + virtual TaggedPointerVendor* GetTaggedPointerVendor () { @@ -354,9 +261,6 @@ public: ClassDescriptorSP GetNonKVOClassDescriptor (ObjCISA isa); - virtual - ~ObjCLanguageRuntime(); - lldb::LanguageType GetLanguageType () const override { @@ -393,13 +297,13 @@ public: lldb::TypeSP LookupInCompleteClassCache (ConstString &name); - virtual ClangUtilityFunction * + virtual UtilityFunction * CreateObjectChecker (const char *) = 0; virtual ObjCRuntimeVersions - GetRuntimeVersion () + GetRuntimeVersion () const { - return eObjC_VersionUnknown; + return ObjCRuntimeVersions::eObjC_VersionUnknown; } bool @@ -433,14 +337,14 @@ public: virtual DeclVendor * GetDeclVendor() { - return NULL; + return nullptr; } // Finds the byte offset of the child_type ivar in parent_type. If it can't find the // offset, returns LLDB_INVALID_IVAR_OFFSET. virtual size_t - GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); + GetByteOffsetForIvar (CompilerType &parent_qual_type, const char *ivar_name); // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol), // try to determine from the runtime what the value of that symbol would be. @@ -451,94 +355,6 @@ public: return LLDB_INVALID_ADDRESS; } - //------------------------------------------------------------------ - /// Chop up an objective C function prototype. - /// - /// Chop up an objective C function fullname and optionally fill in - /// any non-NULL ConstString objects. If a ConstString * is NULL, - /// then this name doesn't get filled in - /// - /// @param[in] name - /// A fully specified objective C function name. The string might - /// contain a category and it includes the leading "+" or "-" and - /// the square brackets, no types for the arguments, just the plain - /// selector. A few examples: - /// "-[NSStringDrawingContext init]" - /// "-[NSStringDrawingContext addString:inRect:]" - /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" - /// "+[NSString(NSStringDrawing) usesFontLeading]" - /// - /// @param[out] class_name - /// If non-NULL, this string will be filled in with the class - /// name including the category. The examples above would return: - /// "NSStringDrawingContext" - /// "NSStringDrawingContext" - /// "NSString(NSStringDrawing)" - /// "NSString(NSStringDrawing)" - /// - /// @param[out] selector_name - /// If non-NULL, this string will be filled in with the selector - /// name. The examples above would return: - /// "init" - /// "addString:inRect:" - /// "sizeWithAttributes:" - /// "usesFontLeading" - /// - /// @param[out] name_sans_category - /// If non-NULL, this string will be filled in with the class - /// name _without_ the category. If there is no category, and empty - /// string will be returned (as the result would be normally returned - /// in the "class_name" argument). The examples above would return: - /// - /// - /// "-[NSString sizeWithAttributes:]" - /// "+[NSString usesFontLeading]" - /// - /// @param[out] class_name_sans_category - /// If non-NULL, this string will be filled in with the prototype - /// name _without_ the category. If there is no category, and empty - /// string will be returned (as this is already the value that was - /// passed in). The examples above would return: - /// - /// - /// "NSString" - /// "NSString" - /// - /// @return - /// Returns the number of strings that were successfully filled - /// in. - //------------------------------------------------------------------ -// static uint32_t -// ParseMethodName (const char *name, -// ConstString *class_name, // Class name (with category if there is one) -// ConstString *selector_name, // selector only -// ConstString *name_sans_category, // full function name with no category (empty if no category) -// ConstString *class_name_sans_category);// Class name without category (empty if no category) - - static bool - IsPossibleObjCMethodName (const char *name) - { - if (!name) - return false; - bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; - bool ends_right = (name[strlen(name) - 1] == ']'); - return (starts_right && ends_right); - } - - static bool - IsPossibleObjCSelector (const char *name) - { - if (!name) - return false; - - if (strchr(name, ':') == NULL) - return true; - else if (name[strlen(name) - 1] == ':') - return true; - else - return false; - } - bool HasNewLiteralsAndIndexing () { @@ -560,7 +376,7 @@ public: } bool - GetTypeBitSize (const ClangASTType& clang_type, + GetTypeBitSize (const CompilerType& compiler_type, uint64_t &size) override; protected: @@ -568,13 +384,12 @@ protected: // Classes that inherit from ObjCLanguageRuntime can see and modify these //------------------------------------------------------------------ ObjCLanguageRuntime(Process *process); - + virtual bool CalculateHasNewLiteralsAndIndexing() { return false; } - bool ISAIsCached (ObjCISA isa) const { @@ -621,11 +436,13 @@ private: sel_addr = LLDB_INVALID_ADDRESS; class_addr = LLDB_INVALID_ADDRESS; } + ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) : class_addr (in_class_addr), sel_addr(in_sel_addr) { } + bool operator== (const ClassAndSel &rhs) { if (class_addr == rhs.class_addr @@ -702,4 +519,4 @@ protected: } // namespace lldb_private -#endif // liblldb_ObjCLanguageRuntime_h_ +#endif // liblldb_ObjCLanguageRuntime_h_ diff --git a/include/lldb/Target/OperatingSystem.h b/include/lldb/Target/OperatingSystem.h index f1c0eb06026f..74de5645da5a 100644 --- a/include/lldb/Target/OperatingSystem.h +++ b/include/lldb/Target/OperatingSystem.h @@ -32,7 +32,6 @@ namespace lldb_private { class OperatingSystem : public PluginInterface - { public: //------------------------------------------------------------------ @@ -58,8 +57,7 @@ public: //------------------------------------------------------------------ OperatingSystem (Process *process); - virtual - ~OperatingSystem(); + ~OperatingSystem() override; //------------------------------------------------------------------ // Plug-in Methods @@ -98,4 +96,4 @@ private: } // namespace lldb_private -#endif // #ifndef liblldb_OperatingSystem_h_ +#endif // liblldb_OperatingSystem_h_ diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index feaac57b128a..53c17a6a66cf 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -37,7 +37,6 @@ namespace lldb_private { class ModuleCache; - enum MmapFlags { eMmapFlagsPrivate = 1, eMmapFlagsAnon = 2 @@ -46,11 +45,11 @@ class ModuleCache; class PlatformProperties : public Properties { public: + PlatformProperties(); + static ConstString GetSettingName (); - PlatformProperties(); - bool GetUseModuleCache () const; bool @@ -81,6 +80,19 @@ class ModuleCache; public PluginInterface { public: + //------------------------------------------------------------------ + /// Default Constructor + //------------------------------------------------------------------ + Platform (bool is_host_platform); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + ~Platform() override; + static void Initialize (); @@ -130,20 +142,6 @@ class ModuleCache; static lldb::PlatformSP GetConnectedRemotePlatformAtIndex (uint32_t idx); - //------------------------------------------------------------------ - /// Default Constructor - //------------------------------------------------------------------ - Platform (bool is_host_platform); - - //------------------------------------------------------------------ - /// Destructor. - /// - /// The destructor is virtual since this class is designed to be - /// inherited from by the plug-in instance. - //------------------------------------------------------------------ - virtual - ~Platform(); - //------------------------------------------------------------------ /// Find a platform plugin for a given process. /// @@ -156,7 +154,7 @@ class ModuleCache; /// /// @param[in] plugin_name /// An optional name of a specific platform plug-in that - /// should be used. If NULL, pick the best plug-in. + /// should be used. If nullptr, pick the best plug-in. //------------------------------------------------------------------ // static lldb::PlatformSP // FindPlugin (Process *process, const ConstString &plugin_name); @@ -185,7 +183,6 @@ class ModuleCache; lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr); - //------------------------------------------------------------------ /// Find a symbol file given a symbol file module specification. /// @@ -247,10 +244,21 @@ class ModuleCache; ResolveRemotePath (const FileSpec &platform_path, FileSpec &resolved_platform_path); - bool + //------------------------------------------------------------------ + /// Get the OS version from a connected platform. + /// + /// Some platforms might not be connected to a remote platform, but + /// can figure out the OS version for a process. This is common for + /// simulator platforms that will run native programs on the current + /// host, but the simulator might be simulating a different OS. The + /// \a process parameter might be specified to help to determine + /// the OS version. + //------------------------------------------------------------------ + virtual bool GetOSVersion (uint32_t &major, uint32_t &minor, - uint32_t &update); + uint32_t &update, + Process *process = nullptr); bool SetOSVersion (uint32_t major, @@ -269,6 +277,9 @@ class ModuleCache; virtual const char * GetHostname (); + + virtual ConstString + GetFullNameForDylib (ConstString basename); virtual const char * GetDescription () = 0; @@ -473,9 +484,16 @@ class ModuleCache; virtual lldb::ProcessSP DebugProcess (ProcessLaunchInfo &launch_info, Debugger &debugger, - Target *target, // Can be NULL, if NULL create a new target, else use existing one + Target *target, // Can be nullptr, if nullptr create a new target, else use existing one Error &error); + virtual lldb::ProcessSP + ConnectProcess (const char* connect_url, + const char* plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Error &error); + //------------------------------------------------------------------ /// Attach to an existing process using a process ID. /// @@ -497,7 +515,7 @@ class ModuleCache; virtual lldb::ProcessSP Attach (ProcessAttachInfo &attach_info, Debugger &debugger, - Target *target, // Can be NULL, if NULL create a new target, else use existing one + Target *target, // Can be nullptr, if nullptr create a new target, else use existing one Error &error) = 0; //------------------------------------------------------------------ @@ -593,6 +611,7 @@ class ModuleCache; { return m_max_uid_name_len; } + // Used for column widths size_t GetMaxGroupIDNameLength() const @@ -829,15 +848,15 @@ class ModuleCache; virtual lldb_private::OptionGroupOptions * GetConnectionOptions (CommandInterpreter& interpreter) { - return NULL; + return nullptr; } virtual lldb_private::Error - RunShellCommand(const char *command, // Shouldn't be NULL + RunShellCommand(const char *command, // Shouldn't be nullptr const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory - int *status_ptr, // Pass NULL if you don't want the process exit status - int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit - std::string *command_output, // Pass NULL if you don't want the command output + int *status_ptr, // Pass nullptr if you don't want the process exit status + int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit + std::string *command_output, // Pass nullptr if you don't want the command output uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish virtual void @@ -945,9 +964,105 @@ class ModuleCache; virtual const std::vector & GetTrapHandlerSymbolNames (); + //------------------------------------------------------------------ + /// Find a support executable that may not live within in the + /// standard locations related to LLDB. + /// + /// Executable might exist within the Platform SDK directories, or + /// in standard tool directories within the current IDE that is + /// running LLDB. + /// + /// @param[in] basename + /// The basename of the executable to locate in the current + /// platform. + /// + /// @return + /// A FileSpec pointing to the executable on disk, or an invalid + /// FileSpec if the executable cannot be found. + //------------------------------------------------------------------ + virtual FileSpec + LocateExecutable (const char *basename) + { + return FileSpec(); + } + + //------------------------------------------------------------------ + /// Allow the platform to set preferred memory cache line size. If non-zero (and the user + /// has not set cache line size explicitly), this value will be used as the cache line + /// size for memory reads. + //------------------------------------------------------------------ + virtual uint32_t + GetDefaultMemoryCacheLineSize() { return 0; } + + //------------------------------------------------------------------ + /// Load a shared library into this process. + /// + /// Try and load a shared library into the current process. This + /// call might fail in the dynamic loader plug-in says it isn't safe + /// to try and load shared libraries at the moment. + /// + /// @param[in] process + /// The process to load the image. + /// + /// @param[in] local_file + /// The file spec that points to the shared library that you want + /// to load if the library is located on the host. The library will + /// be copied over to the location specified by remote_file or into + /// the current working directory with the same filename if the + /// remote_file isn't specified. + /// + /// @param[in] remote_file + /// If local_file is specified then the location where the library + /// should be copied over from the host. If local_file isn't + /// specified, then the path for the shared library on the target + /// what you want to load. + /// + /// @param[out] error + /// An error object that gets filled in with any errors that + /// might occur when trying to load the shared library. + /// + /// @return + /// A token that represents the shared library that can be + /// later used to unload the shared library. A value of + /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared + /// library can't be opened. + //------------------------------------------------------------------ + uint32_t + LoadImage (lldb_private::Process* process, + const lldb_private::FileSpec& local_file, + const lldb_private::FileSpec& remote_file, + lldb_private::Error& error); + + virtual uint32_t + DoLoadImage (lldb_private::Process* process, + const lldb_private::FileSpec& remote_file, + lldb_private::Error& error); + + virtual Error + UnloadImage (lldb_private::Process* process, uint32_t image_token); + + //------------------------------------------------------------------ + /// Connect to all processes waiting for a debugger to attach + /// + /// If the platform have a list of processes waiting for a debugger + /// to connect to them then connect to all of these pending processes. + /// + /// @param[in] debugger + /// The debugger used for the connect. + /// + /// @param[out] error + /// If an error occurred during the connect then this object will + /// contain the error message. + /// + /// @return + /// The number of processes we are succesfully connected to. + //------------------------------------------------------------------ + virtual size_t + ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error); + protected: bool m_is_host; - // Set to true when we are able to actually set the OS version while + // Set to true when we are able to actually set the OS version while // being connected. For remote platforms, we might set the version ahead // of time before we actually connect and this version might change when // we actually connect to a remote platform. For the host platform this @@ -1000,16 +1115,12 @@ class ModuleCache; GetCachedUserName (uint32_t uid) { Mutex::Locker locker (m_mutex); - IDToNameMap::iterator pos = m_uid_map.find (uid); - if (pos != m_uid_map.end()) - { - // return the empty string if our string is NULL - // so we can tell when things were in the negative - // cached (didn't find a valid user name, don't keep - // trying) - return pos->second.AsCString(""); - } - return NULL; + // return the empty string if our string is NULL + // so we can tell when things were in the negative + // cached (didn't find a valid user name, don't keep + // trying) + const auto pos = m_uid_map.find(uid); + return ((pos != m_uid_map.end()) ? pos->second.AsCString("") : nullptr); } const char * @@ -1030,7 +1141,6 @@ class ModuleCache; Mutex::Locker locker (m_mutex); m_uid_map[uid] = ConstString(); } - void ClearCachedUserNames () @@ -1043,16 +1153,12 @@ class ModuleCache; GetCachedGroupName (uint32_t gid) { Mutex::Locker locker (m_mutex); - IDToNameMap::iterator pos = m_gid_map.find (gid); - if (pos != m_gid_map.end()) - { - // return the empty string if our string is NULL - // so we can tell when things were in the negative - // cached (didn't find a valid group name, don't keep - // trying) - return pos->second.AsCString(""); - } - return NULL; + // return the empty string if our string is NULL + // so we can tell when things were in the negative + // cached (didn't find a valid group name, don't keep + // trying) + const auto pos = m_gid_map.find(gid); + return ((pos != m_gid_map.end()) ? pos->second.AsCString("") : nullptr); } const char * @@ -1092,6 +1198,10 @@ class ModuleCache; const uint64_t src_offset, const uint64_t src_size, const FileSpec& dst_file_spec); + + virtual Error + DownloadSymbolFile (const lldb::ModuleSP& module_sp, + const FileSpec& dst_file_spec); virtual const char * GetCacheHostname (); @@ -1123,7 +1233,6 @@ class ModuleCache; DISALLOW_COPY_AND_ASSIGN (Platform); }; - class PlatformList { public: @@ -1133,11 +1242,9 @@ class ModuleCache; m_selected_platform_sp() { } - - ~PlatformList() - { - } - + + ~PlatformList() = default; + void Append (const lldb::PlatformSP &platform_sp, bool set_selected) { @@ -1220,22 +1327,21 @@ class ModuleCache; public: OptionGroupPlatformRSync (); - virtual - ~OptionGroupPlatformRSync (); + ~OptionGroupPlatformRSync() override; - virtual lldb_private::Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + lldb_private::Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; void - OptionParsingStarting (CommandInterpreter &interpreter); + OptionParsingStarting(CommandInterpreter &interpreter) override; const lldb_private::OptionDefinition* - GetDefinitions (); + GetDefinitions() override; - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; // Options table: Required for subclasses of Options. @@ -1256,22 +1362,21 @@ class ModuleCache; public: OptionGroupPlatformSSH (); - virtual - ~OptionGroupPlatformSSH (); + ~OptionGroupPlatformSSH() override; - virtual lldb_private::Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + lldb_private::Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; void - OptionParsingStarting (CommandInterpreter &interpreter); + OptionParsingStarting(CommandInterpreter &interpreter) override; - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; const lldb_private::OptionDefinition* - GetDefinitions (); + GetDefinitions() override; // Options table: Required for subclasses of Options. @@ -1283,7 +1388,6 @@ class ModuleCache; std::string m_ssh_opts; private: - DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformSSH); }; @@ -1292,22 +1396,21 @@ class ModuleCache; public: OptionGroupPlatformCaching (); - virtual - ~OptionGroupPlatformCaching (); + ~OptionGroupPlatformCaching() override; - virtual lldb_private::Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + lldb_private::Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; void - OptionParsingStarting (CommandInterpreter &interpreter); + OptionParsingStarting(CommandInterpreter &interpreter) override; - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; const lldb_private::OptionDefinition* - GetDefinitions (); + GetDefinitions() override; // Options table: Required for subclasses of Options. @@ -1316,10 +1419,11 @@ class ModuleCache; // Instance variables to hold the values for command options. std::string m_cache_dir; + private: DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformCaching); }; } // namespace lldb_private -#endif // liblldb_Platform_h_ +#endif // liblldb_Platform_h_ diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index f75b3cd5683d..2e063c5bbccc 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -17,8 +17,10 @@ // C++ Includes #include -#include +#include +#include #include +#include // Other libraries and framework includes // Project includes @@ -55,11 +57,10 @@ struct Range; class ProcessProperties : public Properties { public: - // Pass NULL for "process" if the ProcessProperties are to be the global copy + // Pass nullptr for "process" if the ProcessProperties are to be the global copy ProcessProperties (lldb_private::Process *process); - virtual - ~ProcessProperties(); + ~ProcessProperties() override; bool GetDisableMemoryCache() const; @@ -103,12 +104,14 @@ public: void SetDetachKeepsStopped (bool keep_stopped); -protected: + bool + GetWarningsOptimization () const; +protected: static void OptionValueChangedCallback (void *baton, OptionValue *option_value); - Process * m_process; // Can be NULL for global ProcessProperties + Process * m_process; // Can be nullptr for global ProcessProperties }; typedef std::shared_ptr ProcessPropertiesSP; @@ -236,7 +239,8 @@ public: m_wait_for_launch (false), m_ignore_existing (true), m_continue_once_attached (false), - m_detach_on_error (true) + m_detach_on_error (true), + m_async (false) { } @@ -249,7 +253,8 @@ public: m_wait_for_launch (false), m_ignore_existing (true), m_continue_once_attached (false), - m_detach_on_error(true) + m_detach_on_error (true), + m_async (false) { ProcessInfo::operator= (launch_info); SetProcessPluginName (launch_info.GetProcessPluginName()); @@ -271,6 +276,18 @@ public: m_wait_for_launch = b; } + bool + GetAsync () const + { + return m_async; + } + + void + SetAsync (bool b) + { + m_async = b; + } + bool GetIgnoreExisting () const { @@ -310,9 +327,7 @@ public: const char * GetProcessPluginName () const { - if (m_plugin_name.empty()) - return NULL; - return m_plugin_name.c_str(); + return (m_plugin_name.empty() ? nullptr : m_plugin_name.c_str()); } void @@ -384,7 +399,6 @@ public: m_listener_sp = listener_sp; } - Listener & GetListenerForProcess (Debugger &debugger); @@ -397,35 +411,33 @@ protected: bool m_ignore_existing; bool m_continue_once_attached; // Supports the use-case scenario of immediately continuing the process once attached. bool m_detach_on_error; // If we are debugging remotely, instruct the stub to detach rather than killing the target on error. + bool m_async; // Use an async attach where we start the attach and return immediately (used by GUI programs with --waitfor so they can call SBProcess::Stop() to cancel attach) }; class ProcessLaunchCommandOptions : public Options { public: - ProcessLaunchCommandOptions (CommandInterpreter &interpreter) : Options(interpreter) { // Keep default values of all options in one place: OptionParsingStarting () OptionParsingStarting (); } - - ~ProcessLaunchCommandOptions () - { - } - + + ~ProcessLaunchCommandOptions() override = default; + Error - SetOptionValue (uint32_t option_idx, const char *option_arg); + SetOptionValue (uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting () + OptionParsingStarting() override { launch_info.Clear(); disable_aslr = eLazyBoolCalculate; } const OptionDefinition* - GetDefinitions () + GetDefinitions() override { return g_option_table; } @@ -521,11 +533,8 @@ protected: class ProcessInstanceInfoList { public: - ProcessInstanceInfoList () : - m_infos() - { - } - + ProcessInstanceInfoList() = default; + void Clear() { @@ -547,25 +556,19 @@ public: const char * GetProcessNameAtIndex (size_t idx) { - if (idx < m_infos.size()) - return m_infos[idx].GetName(); - return NULL; + return ((idx < m_infos.size()) ? m_infos[idx].GetName() : nullptr); } size_t GetProcessNameLengthAtIndex (size_t idx) { - if (idx < m_infos.size()) - return m_infos[idx].GetNameLength(); - return 0; + return ((idx < m_infos.size()) ? m_infos[idx].GetNameLength() : 0); } lldb::pid_t GetProcessIDAtIndex (size_t idx) { - if (idx < m_infos.size()) - return m_infos[idx].GetProcessID(); - return 0; + return ((idx < m_infos.size()) ? m_infos[idx].GetProcessID() : 0); } bool @@ -592,7 +595,6 @@ protected: collection m_infos; }; - // This class tracks the Modification state of the process. Things that can currently modify // the program are running the program (which will up the StopID) and writing memory (which // will up the MemoryID.) @@ -600,7 +602,7 @@ protected: class ProcessModID { -friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); + friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); public: ProcessModID () : m_stop_id (0), @@ -626,7 +628,7 @@ public: return *this; } - ~ProcessModID () {} + ~ProcessModID() = default; void BumpStopID () { m_stop_id++; @@ -709,6 +711,7 @@ private: uint32_t m_running_user_expression; lldb::EventSP m_last_natural_stop_event; }; + inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs) { if (lhs.StopIDEqual (rhs) @@ -720,11 +723,7 @@ inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs) inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs) { - if (!lhs.StopIDEqual (rhs) - || !lhs.MemoryIDEqual (rhs)) - return true; - else - return false; + return (!lhs.StopIDEqual (rhs) || !lhs.MemoryIDEqual (rhs)); } //---------------------------------------------------------------------- @@ -739,7 +738,7 @@ class Process : public ExecutionContextScope, public PluginInterface { - friend class ClangFunction; // For WaitForStateChangeEventsPrivate + friend class FunctionCaller; // For WaitForStateChangeEventsPrivate friend class Debugger; // For PopProcessIOHandler and ProcessIOHandlerIsActive friend class ProcessEventData; friend class StopInfo; @@ -747,7 +746,6 @@ class Process : friend class ThreadList; public: - //------------------------------------------------------------------ /// Broadcaster event bits definitions. //------------------------------------------------------------------ @@ -766,6 +764,14 @@ public: eBroadcastInternalStateControlPause = (1<<1), eBroadcastInternalStateControlResume = (1<<2) }; + + //------------------------------------------------------------------ + /// Process warning types. + //------------------------------------------------------------------ + enum Warnings + { + eWarningsOptimization = 1 + }; typedef Range LoadRange; // We use a read/write lock to allow on or more clients to @@ -781,12 +787,11 @@ public: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } - //------------------------------------------------------------------ /// A notification structure that can be used by clients to listen /// for changes in a process's lifetime. @@ -811,13 +816,13 @@ public: ProcessEventData (); ProcessEventData (const lldb::ProcessSP &process, lldb::StateType state); - virtual ~ProcessEventData(); + ~ProcessEventData() override; static const ConstString & GetFlavorString (); - virtual const ConstString & - GetFlavor () const; + const ConstString & + GetFlavor() const override; lldb::ProcessSP GetProcessSP() const @@ -845,10 +850,7 @@ public: const char * GetRestartedReasonAtIndex(size_t idx) { - if (idx > m_restarted_reasons.size()) - return NULL; - else - return m_restarted_reasons[idx].c_str(); + return ((idx < m_restarted_reasons.size()) ? m_restarted_reasons[idx].c_str() : nullptr); } bool @@ -857,11 +859,11 @@ public: return m_interrupted; } - virtual void - Dump (Stream *s) const; + void + Dump(Stream *s) const override; - virtual void - DoOnRemoval (Event *event_ptr); + void + DoOnRemoval(Event *event_ptr) override; static const Process::ProcessEventData * GetEventDataFromEvent (const Event *event_ptr); @@ -897,22 +899,24 @@ public: SetUpdateStateOnRemoval (Event *event_ptr); private: - void SetUpdateStateOnRemoval() { m_update_state++; } + void SetRestarted (bool new_value) { m_restarted = new_value; } + void SetInterrupted (bool new_value) { m_interrupted = new_value; } + void AddRestartedReason (const char *reason) { @@ -925,32 +929,22 @@ public: bool m_restarted; // For "eStateStopped" events, this is true if the target was automatically restarted. int m_update_state; bool m_interrupted; - DISALLOW_COPY_AND_ASSIGN (ProcessEventData); + DISALLOW_COPY_AND_ASSIGN (ProcessEventData); }; - -#endif - - static void - SettingsInitialize (); - - static void - SettingsTerminate (); - - static const ProcessPropertiesSP & - GetGlobalProperties(); +#endif // SWIG //------------------------------------------------------------------ /// Construct with a shared pointer to a target, and the Process listener. /// Uses the Host UnixSignalsSP by default. //------------------------------------------------------------------ - Process(Target &target, Listener &listener); + Process(lldb::TargetSP target_sp, Listener &listener); //------------------------------------------------------------------ /// Construct with a shared pointer to a target, the Process listener, /// and the appropriate UnixSignalsSP for the process. //------------------------------------------------------------------ - Process(Target &target, Listener &listener, const lldb::UnixSignalsSP &unix_signals_sp); + Process(lldb::TargetSP target_sp, Listener &listener, const lldb::UnixSignalsSP &unix_signals_sp); //------------------------------------------------------------------ /// Destructor. @@ -958,8 +952,16 @@ public: /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. //------------------------------------------------------------------ - virtual - ~Process(); + ~Process() override; + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + + static const ProcessPropertiesSP & + GetGlobalProperties(); //------------------------------------------------------------------ /// Find a Process plug-in that can debug \a module using the @@ -973,20 +975,18 @@ public: /// The module shared pointer that this process will debug. /// /// @param[in] plugin_name - /// If NULL, select the best plug-in for the binary. If non-NULL + /// If nullptr, select the best plug-in for the binary. If non-nullptr /// then look for a plugin whose PluginInfo's name matches /// this string. /// /// @see Process::CanDebug () //------------------------------------------------------------------ static lldb::ProcessSP - FindPlugin (Target &target, + FindPlugin (lldb::TargetSP target_sp, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path); - - //------------------------------------------------------------------ /// Static function that can be used with the \b host function /// Host::StartMonitoringChildProcess (). @@ -997,16 +997,16 @@ public: /// Subclasses should call Host::StartMonitoringChildProcess () /// with: /// callback = Process::SetHostProcessExitStatus - /// callback_baton = NULL + /// callback_baton = nullptr /// pid = Process::GetID() /// monitor_signals = false //------------------------------------------------------------------ static bool - SetProcessExitStatus (void *callback_baton, // The callback baton which should be set to NULL - lldb::pid_t pid, // The process ID we want to monitor - bool exited, - int signo, // Zero for no signal - int status); // Exit value of process if signal is zero + SetProcessExitStatus(void *callback_baton, // The callback baton which should be set to nullptr + lldb::pid_t pid, // The process ID we want to monitor + bool exited, + int signo, // Zero for no signal + int status); // Exit value of process if signal is zero lldb::ByteOrder GetByteOrder () const; @@ -1019,6 +1019,7 @@ public: { return m_process_unique_id; } + //------------------------------------------------------------------ /// Check if a plug-in instance can debug the file in \a module. /// @@ -1031,10 +1032,9 @@ public: /// debug the executable, \b false otherwise. //------------------------------------------------------------------ virtual bool - CanDebug (Target &target, + CanDebug (lldb::TargetSP target, bool plugin_specified_by_name) = 0; - //------------------------------------------------------------------ /// This object is about to be destroyed, do any necessary cleanup. /// @@ -1043,8 +1043,7 @@ public: //------------------------------------------------------------------ virtual void Finalize(); - - + //------------------------------------------------------------------ /// Return whether this object is valid (i.e. has not been finalized.) /// @@ -1075,7 +1074,7 @@ public: virtual CommandObject * GetPluginCommandObject() { - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -1163,7 +1162,7 @@ public: /// /// @return /// Returns a pointer to the SystemRuntime plugin for this Process - /// if one is available. Else returns NULL. + /// if one is available. Else returns nullptr. //------------------------------------------------------------------ virtual SystemRuntime * GetSystemRuntime (); @@ -1194,7 +1193,7 @@ public: /// @param[in] strm /// A stream where output intended for the user /// (if the driver has a way to display that) generated during - /// the connection. This may be NULL if no output is needed.A + /// the connection. This may be nullptr if no output is needed.A /// /// @param[in] remote_url /// The URL format that we are connecting to. @@ -1236,31 +1235,24 @@ public: GetImageInfoAddress (); //------------------------------------------------------------------ - /// Load a shared library into this process. - /// - /// Try and load a shared library into the current process. This - /// call might fail in the dynamic loader plug-in says it isn't safe - /// to try and load shared libraries at the moment. - /// - /// @param[in] image_spec - /// The image file spec that points to the shared library that - /// you want to load. + /// Called when the process is about to broadcast a public stop. /// - /// @param[out] error - /// An error object that gets filled in with any errors that - /// might occur when trying to load the shared library. - /// - /// @return - /// A token that represents the shared library that can be - /// later used to unload the shared library. A value of - /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared - /// library can't be opened. + /// There are public and private stops. Private stops are when the + /// process is doing things like stepping and the client doesn't + /// need to know about starts and stop that implement a thread plan. + /// Single stepping over a source line in code might end up being + /// implemented by one or more process starts and stops. Public stops + /// are when clients will be notified that the process is stopped. + /// These events typically trigger UI updates (thread stack frames to + /// be displayed, variables to be displayed, and more). This function + /// can be overriden and allows process subclasses to do something + /// before the eBroadcastBitStateChanged event is sent to public + /// clients. //------------------------------------------------------------------ - virtual uint32_t - LoadImage (const FileSpec &image_spec, Error &error); - - virtual Error - UnloadImage (uint32_t image_token); + virtual void + WillPublicStop () + { + } //------------------------------------------------------------------ /// Register for process and thread notifications. @@ -1278,6 +1270,7 @@ public: void RegisterNotificationCallbacks (const Process::Notifications& callbacks); #endif + //------------------------------------------------------------------ /// Unregister for process and thread notifications. /// @@ -1298,6 +1291,7 @@ public: bool UnregisterNotificationCallbacks (const Process::Notifications& callbacks); #endif + //================================================================== // Built in Process Control functions //================================================================== @@ -1334,6 +1328,7 @@ public: Error ResumeSynchronous (Stream *stream); + //------------------------------------------------------------------ /// Halts a running process. /// @@ -1346,12 +1341,15 @@ public: /// @param[in] clear_thread_plans /// If true, when the process stops, clear all thread plans. /// + /// @param[in] use_run_lock + /// Whether to release the run lock after the stop. + /// /// @return /// Returns an error object. If the error is empty, the process is halted. /// otherwise the halt has failed. //------------------------------------------------------------------ Error - Halt (bool clear_thread_plans = false); + Halt (bool clear_thread_plans = false, bool use_run_lock = true); //------------------------------------------------------------------ /// Detaches from a running or stopped process. @@ -1402,7 +1400,7 @@ public: Signal (int signal); void - SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); + SetUnixSignals(lldb::UnixSignalsSP &&signals_sp); const lldb::UnixSignalsSP & GetUnixSignals(); @@ -1447,7 +1445,7 @@ public: /// @param[in] strm /// A stream where output intended for the user /// (if the driver has a way to display that) generated during - /// the connection. This may be NULL if no output is needed.A + /// the connection. This may be nullptr if no output is needed.A /// /// @param[in] remote_url /// The URL format that we are connecting to. @@ -1525,7 +1523,6 @@ public: process_arch.Clear(); } - //------------------------------------------------------------------ /// Called after a process re-execs itself. /// @@ -1590,7 +1587,6 @@ public: return error; } - //------------------------------------------------------------------ /// Called after launching a process. /// @@ -1600,8 +1596,6 @@ public: virtual void DidLaunch () {} - - //------------------------------------------------------------------ /// Called before resuming to a process. /// @@ -1639,7 +1633,6 @@ public: return error; } - //------------------------------------------------------------------ /// Called after resuming a process. /// @@ -1649,7 +1642,6 @@ public: virtual void DidResume () {} - //------------------------------------------------------------------ /// Called before halting to a process. /// @@ -1668,9 +1660,8 @@ public: /// DoHalt must produce one and only one stop StateChanged event if it actually /// stops the process. If the stop happens through some natural event (for /// instance a SIGSTOP), then forwarding that event will do. Otherwise, you must - /// generate the event manually. Note also, the private event thread is stopped when - /// DoHalt is run to prevent the events generated while halting to trigger - /// other state changes before the halt is complete. + /// generate the event manually. This function is called from the context of the + /// private state thread. /// /// @param[out] caused_stop /// If true, then this Halt caused the stop, otherwise, the @@ -1688,7 +1679,6 @@ public: return error; } - //------------------------------------------------------------------ /// Called after halting a process. /// @@ -1728,7 +1718,6 @@ public: return error; } - //------------------------------------------------------------------ /// Called after detaching from a process. /// @@ -1781,7 +1770,6 @@ public: virtual bool DestroyRequiresHalt() { return true; } - //------------------------------------------------------------------ /// Called after sending a signal to a process. /// @@ -1807,6 +1795,41 @@ public: virtual void RefreshStateAfterStop () = 0; + //------------------------------------------------------------------ + /// Sometimes the connection to a process can detect the host OS + /// version that the process is running on. The current platform + /// should be checked first in case the platform is connected, but + /// clients can fall back onto this function if the platform fails + /// to identify the host OS version. The platform should be checked + /// first in case you are running a simulator platform that might + /// itself be running natively, but have different heuristics for + /// figuring out which OS is is emulating. + /// + /// @param[out] major + /// The major OS version, or UINT32_MAX if it can't be determined + /// + /// @param[out] minor + /// The minor OS version, or UINT32_MAX if it can't be determined + /// + /// @param[out] update + /// The update OS version, or UINT32_MAX if it can't be determined + /// + /// @return + /// Returns \b true if the host OS version info was filled in + /// and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + GetHostOSVersion(uint32_t &major, + uint32_t &minor, + uint32_t &update) + { + major = UINT32_MAX; + minor = UINT32_MAX; + update = UINT32_MAX; + return false; + } + + //------------------------------------------------------------------ /// Get the target object pointer for this module. /// @@ -1817,7 +1840,7 @@ public: Target & GetTarget () { - return m_target; + return *m_target_sp.lock(); } //------------------------------------------------------------------ @@ -1830,7 +1853,7 @@ public: const Target & GetTarget () const { - return m_target; + return *m_target_sp.lock(); } //------------------------------------------------------------------ @@ -1888,7 +1911,6 @@ public: virtual void ModulesDidLoad (ModuleList &module_list); - //------------------------------------------------------------------ /// Retrieve the list of shared libraries that are loaded for this process /// @@ -1919,30 +1941,20 @@ public: return StructuredData::ObjectSP(); } -protected: - - void - SetState (lldb::EventSP &event_sp); - - lldb::StateType - GetPrivateState (); - //------------------------------------------------------------------ - /// The "private" side of resuming a process. This doesn't alter the - /// state of m_run_lock, but just causes the process to resume. + /// Print a user-visible warning about a module being built with optimization /// - /// @return - /// An Error object describing the success or failure of the resume. - //------------------------------------------------------------------ - Error - PrivateResume (); - - //------------------------------------------------------------------ - // Called internally + /// Prints a async warning message to the user one time per Module + /// where a function is found that was compiled with optimization, per + /// Process. + /// + /// @param [in] sc + /// A SymbolContext with eSymbolContextFunction and eSymbolContextModule + /// pre-computed. //------------------------------------------------------------------ void - CompleteAttach (); - + PrintWarningOptimization (const SymbolContext &sc); + public: //------------------------------------------------------------------ /// Get the exit status for a process. @@ -1958,13 +1970,12 @@ public: /// Get a textual description of what the process exited. /// /// @return - /// The textual description of why the process exited, or NULL + /// The textual description of why the process exited, or nullptr /// if there is no description available. //------------------------------------------------------------------ const char * GetExitDescription (); - virtual void DidExit () { @@ -2045,7 +2056,7 @@ public: /// otherwise. //------------------------------------------------------------------ virtual bool - IsAlive () = 0; + IsAlive (); //------------------------------------------------------------------ /// Before lldb detaches from a process, it warns the user that they are about to lose their debug session. @@ -2255,7 +2266,6 @@ public: return 0; } - //------------------------------------------------------------------ /// Write all or part of a scalar value to memory. /// @@ -2329,7 +2339,6 @@ public: size_t WriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error); - //------------------------------------------------------------------ /// Actually allocate memory in the process. /// @@ -2352,7 +2361,6 @@ public: return LLDB_INVALID_ADDRESS; } - //------------------------------------------------------------------ /// The public interface to allocating memory in the process. /// @@ -2369,16 +2377,41 @@ public: /// that a block that isn't set writable can still be written on from lldb, /// just not by the process itself. /// - /// @param[in/out] error + /// @param[in,out] error /// An error object to fill in if things go wrong. /// @return /// The address of the allocated buffer in the process, or /// LLDB_INVALID_ADDRESS if the allocation failed. //------------------------------------------------------------------ - lldb::addr_t AllocateMemory (size_t size, uint32_t permissions, Error &error); + //------------------------------------------------------------------ + /// The public interface to allocating memory in the process, this also + /// clears the allocated memory. + /// + /// This function will allocate memory in the process's address + /// space. This can't rely on the generic function calling mechanism, + /// since that requires this function. + /// + /// @param[in] size + /// The size of the allocation requested. + /// + /// @param[in] permissions + /// Or together any of the lldb::Permissions bits. The permissions on + /// a given memory allocation can't be changed after allocation. Note + /// that a block that isn't set writable can still be written on from lldb, + /// just not by the process itself. + /// + /// @param[in/out] error + /// An error object to fill in if things go wrong. + /// @return + /// The address of the allocated buffer in the process, or + /// LLDB_INVALID_ADDRESS if the allocation failed. + //------------------------------------------------------------------ + + lldb::addr_t + CallocateMemory (size_t size, uint32_t permissions, Error &error); //------------------------------------------------------------------ /// Resolve dynamically loaded indirect functions. @@ -2393,7 +2426,6 @@ public: /// The address of the resolved function. /// LLDB_INVALID_ADDRESS if the resolution failed. //------------------------------------------------------------------ - virtual lldb::addr_t ResolveIndirectFunction(const Address *address, Error &error); @@ -2518,7 +2550,6 @@ public: /// @return /// \btrue if the memory was deallocated, \bfalse otherwise. //------------------------------------------------------------------ - virtual Error DoDeallocateMemory (lldb::addr_t ptr) { @@ -2527,7 +2558,6 @@ public: return error; } - //------------------------------------------------------------------ /// The public interface to deallocating memory in the process. /// @@ -2541,7 +2571,6 @@ public: /// @return /// \btrue if the memory was deallocated, \bfalse otherwise. //------------------------------------------------------------------ - Error DeallocateMemory (lldb::addr_t ptr); @@ -2671,7 +2700,6 @@ public: return error; } - virtual Error DisableBreakpointSite (BreakpointSite *bp_site) { @@ -2680,7 +2708,6 @@ public: return error; } - // This is implemented completely using the lldb::Process API. Subclasses // don't need to implement this function unless the standard flow of // read existing opcode, write breakpoint opcode, verify breakpoint opcode @@ -2717,7 +2744,6 @@ public: Error EnableBreakpointSiteByID (lldb::user_id_t break_id); - // BreakpointLocations use RemoveOwnerFromBreakpointSite to remove // themselves from the owner's list of this breakpoint sites. void @@ -2811,12 +2837,16 @@ public: // Returns the process state when it is stopped. If specified, event_sp_ptr // is set to the event which triggered the stop. If wait_always = false, // and the process is already stopped, this function returns immediately. + // If the process is hijacked and use_run_lock is true (the default), then this + // function releases the run lock after the stop. Setting use_run_lock to false + // will avoid this behavior. lldb::StateType - WaitForProcessToStop (const TimeValue *timeout, - lldb::EventSP *event_sp_ptr = NULL, - bool wait_always = true, - Listener *hijack_listener = NULL, - Stream *stream = NULL); + WaitForProcessToStop(const TimeValue *timeout, + lldb::EventSP *event_sp_ptr = nullptr, + bool wait_always = true, + Listener *hijack_listener = nullptr, + Stream *stream = nullptr, + bool use_run_lock = true); uint32_t GetIOHandlerID () const @@ -2838,9 +2868,9 @@ public: SyncIOHandler (uint32_t iohandler_id, uint64_t timeout_msec); lldb::StateType - WaitForStateChangedEvents (const TimeValue *timeout, - lldb::EventSP &event_sp, - Listener *hijack_listener); // Pass NULL to use builtin listener + WaitForStateChangedEvents(const TimeValue *timeout, + lldb::EventSP &event_sp, + Listener *hijack_listener); // Pass nullptr to use builtin listener //-------------------------------------------------------------------------------------- /// Centralize the code that handles and prints descriptions for process state changes. @@ -2851,7 +2881,7 @@ public: /// @param[in] stream /// The output stream to get the state change description /// - /// @param[inout] pop_process_io_handler + /// @param[in,out] pop_process_io_handler /// If this value comes in set to \b true, then pop the Process IOHandler if needed. /// Else this variable will be set to \b true or \b false to indicate if the process /// needs to have its process IOHandler popped. @@ -2863,9 +2893,9 @@ public: HandleProcessStateChangedEvent (const lldb::EventSP &event_sp, Stream *stream, bool &pop_process_io_handler); + Event * PeekAtStateChangedEvents (); - class ProcessEventHijacker @@ -2876,6 +2906,7 @@ public: { m_process.HijackProcessEvents (listener); } + ~ProcessEventHijacker () { m_process.RestoreProcessEvents(); @@ -2884,6 +2915,7 @@ public: private: Process &m_process; }; + friend class ProcessEventHijacker; friend class ProcessProperties; //------------------------------------------------------------------ @@ -2910,27 +2942,6 @@ public: void RestoreProcessEvents (); -private: - //------------------------------------------------------------------ - /// This is the part of the event handling that for a process event. - /// It decides what to do with the event and returns true if the - /// event needs to be propagated to the user, and false otherwise. - /// If the event is not propagated, this call will most likely set - /// the target to executing again. - /// There is only one place where this call should be called, HandlePrivateEvent. - /// Don't call it from anywhere else... - /// - /// @param[in] event_ptr - /// This is the event we are handling. - /// - /// @return - /// Returns \b true if the event should be reported to the - /// user, \b false otherwise. - //------------------------------------------------------------------ - bool - ShouldBroadcastEvent (Event *event_ptr); - -public: const lldb::ABISP & GetABI (); @@ -3004,29 +3015,29 @@ public: //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ - virtual lldb::TargetSP - CalculateTarget (); + lldb::TargetSP + CalculateTarget() override; - virtual lldb::ProcessSP - CalculateProcess () + lldb::ProcessSP + CalculateProcess() override { return shared_from_this(); } - virtual lldb::ThreadSP - CalculateThread () + lldb::ThreadSP + CalculateThread() override { return lldb::ThreadSP(); } - virtual lldb::StackFrameSP - CalculateStackFrame () + lldb::StackFrameSP + CalculateStackFrame() override { return lldb::StackFrameSP(); } - virtual void - CalculateExecutionContext (ExecutionContext &exe_ctx); + void + CalculateExecutionContext(ExecutionContext &exe_ctx) override; void SetSTDIOFileDescriptor (int file_descriptor); @@ -3129,8 +3140,69 @@ public: return Error("Not supported"); } + size_t + AddImageToken(lldb::addr_t image_ptr); + + lldb::addr_t + GetImagePtrFromToken(size_t token) const; + + void + ResetImageToken(size_t token); + protected: + void + SetState (lldb::EventSP &event_sp); + + lldb::StateType + GetPrivateState (); + + //------------------------------------------------------------------ + /// The "private" side of resuming a process. This doesn't alter the + /// state of m_run_lock, but just causes the process to resume. + /// + /// @return + /// An Error object describing the success or failure of the resume. + //------------------------------------------------------------------ + Error + PrivateResume (); + //------------------------------------------------------------------ + // Called internally + //------------------------------------------------------------------ + void + CompleteAttach (); + + //------------------------------------------------------------------ + /// Print a user-visible warning one time per Process + /// + /// A facility for printing a warning to the user once per repeat_key. + /// + /// warning_type is from the Process::Warnings enums. + /// repeat_key is a pointer value that will be used to ensure that the + /// warning message is not printed multiple times. For instance, with a + /// warning about a function being optimized, you can pass the CompileUnit + /// pointer to have the warning issued for only the first function in a + /// CU, or the Function pointer to have it issued once for every function, + /// or a Module pointer to have it issued once per Module. + /// + /// Classes outside Process should call a specific PrintWarning method + /// so that the warning strings are all centralized in Process, instead of + /// calling PrintWarning() directly. + /// + /// @param [in] warning_type + /// One of the types defined in Process::Warnings. + /// + /// @param [in] repeat_key + /// A pointer value used to ensure that the warning is only printed once. + /// May be nullptr, indicating that the warning is printed unconditionally + /// every time. + /// + /// @param [in] fmt + /// printf style format string + //------------------------------------------------------------------ + void + PrintWarning (uint64_t warning_type, const void *repeat_key, const char *fmt, ...) __attribute__((format(printf, 4, 5))); + //------------------------------------------------------------------ // NextEventAction provides a way to register an action on the next // event that is delivered to this process. There is currently only @@ -3158,10 +3230,8 @@ protected: } virtual - ~NextEventAction() - { - } - + ~NextEventAction() = default; + virtual EventActionResult PerformAction (lldb::EventSP &event_sp) = 0; virtual void HandleBeingUnshipped () {} virtual EventActionResult HandleBeingInterrupted () = 0; @@ -3170,6 +3240,7 @@ protected: { m_process->m_resume_requested = true; } + protected: Process *m_process; }; @@ -3188,25 +3259,17 @@ protected: public: AttachCompletionHandler (Process *process, uint32_t exec_count); - virtual - ~AttachCompletionHandler() - { - } - - virtual EventActionResult PerformAction (lldb::EventSP &event_sp); - virtual EventActionResult HandleBeingInterrupted (); - virtual const char *GetExitString(); + ~AttachCompletionHandler() override = default; + + EventActionResult PerformAction(lldb::EventSP &event_sp) override; + EventActionResult HandleBeingInterrupted() override; + const char *GetExitString() override; + private: uint32_t m_exec_count; std::string m_exit_string; }; - bool - HijackPrivateProcessEvents (Listener *listener); - - void - RestorePrivateProcessEvents (); - bool PrivateStateThreadIsValid () const { @@ -3223,6 +3286,8 @@ protected: // Type definitions //------------------------------------------------------------------ typedef std::map LanguageRuntimeCollection; + typedef std::unordered_set WarningsPointerSet; + typedef std::map WarningsCollection; struct PreResumeCallbackAndBaton { @@ -3238,7 +3303,7 @@ protected: //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ - Target & m_target; ///< The target that owns this process. + std::weak_ptr m_target_sp; ///< The target that owns this process. ThreadSafeValue m_public_state; ThreadSafeValue m_private_state; // The actual state of our process Broadcaster m_private_state_broadcaster; // This broadcaster feeds state changed events into the private state thread's listener. @@ -3290,7 +3355,6 @@ protected: std::vector m_pre_resume_actions; ProcessRunLock m_public_run_lock; ProcessRunLock m_private_run_lock; - Predicate m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done. ArchSpec::StopInfoOverrideCallbackType m_stop_info_override_callback; bool m_currently_handling_do_on_removals; bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check. @@ -3302,6 +3366,7 @@ protected: std::map m_resolved_indirect_addresses; bool m_destroy_in_process; bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, don't support the ability to modify the stack. + WarningsCollection m_warnings_issued; // A set of object pointers which have already had warnings printed enum { eCanJITDontKnow= 0, @@ -3353,6 +3418,9 @@ protected: void HandlePrivateEvent (lldb::EventSP &event_sp); + Error + HaltPrivate(); + lldb::StateType WaitForProcessStopPrivate (const TimeValue *timeout, lldb::EventSP &event_sp); @@ -3401,23 +3469,39 @@ protected: } Error - HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp); + StopForDestroyOrDetach(lldb::EventSP &exit_event_sp); bool StateChangedIsExternallyHijacked(); void LoadOperatingSystemPlugin(bool flush); + private: //------------------------------------------------------------------ - // For Process only + /// This is the part of the event handling that for a process event. + /// It decides what to do with the event and returns true if the + /// event needs to be propagated to the user, and false otherwise. + /// If the event is not propagated, this call will most likely set + /// the target to executing again. + /// There is only one place where this call should be called, HandlePrivateEvent. + /// Don't call it from anywhere else... + /// + /// @param[in] event_ptr + /// This is the event we are handling. + /// + /// @return + /// Returns \b true if the event should be reported to the + /// user, \b false otherwise. //------------------------------------------------------------------ + bool + ShouldBroadcastEvent (Event *event_ptr); + void ControlPrivateStateThread (uint32_t signal); DISALLOW_COPY_AND_ASSIGN (Process); - }; } // namespace lldb_private -#endif // liblldb_Process_h_ +#endif // liblldb_Process_h_ diff --git a/include/lldb/Target/QueueItem.h b/include/lldb/Target/QueueItem.h index c69c825a7976..aea506644c37 100644 --- a/include/lldb/Target/QueueItem.h +++ b/include/lldb/Target/QueueItem.h @@ -10,8 +10,14 @@ #ifndef liblldb_QueueItem_h_ #define liblldb_QueueItem_h_ +// C Includes +// C++ Includes +#include +#include #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" @@ -19,7 +25,6 @@ #include "lldb/Core/Address.h" #include "lldb/Core/ConstString.h" - namespace lldb_private { //------------------------------------------------------------------ @@ -32,12 +37,10 @@ namespace lldb_private { // execution of the item begins. //------------------------------------------------------------------ - class QueueItem : public std::enable_shared_from_this { public: - QueueItem (lldb::QueueSP queue_sp, lldb::ProcessSP process_sp, lldb::addr_t item_ref, lldb_private::Address address); ~QueueItem (); @@ -98,7 +101,7 @@ public: bool IsValid () { - return m_queue_wp.lock() != NULL; + return m_queue_wp.lock() != nullptr; } //------------------------------------------------------------------ @@ -200,7 +203,6 @@ protected: void FetchEntireItem (); - lldb::QueueWP m_queue_wp; lldb::ProcessWP m_process_wp; @@ -220,16 +222,10 @@ protected: std::string m_queue_label; std::string m_target_queue_label; - private: - //------------------------------------------------------------------ - // For QueueItem only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (QueueItem); - }; } // namespace lldb_private -#endif // liblldb_QueueItem_h_ +#endif // liblldb_QueueItem_h_ diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h index 9108d4575259..037c27adaf10 100644 --- a/include/lldb/Target/RegisterContext.h +++ b/include/lldb/Target/RegisterContext.h @@ -29,8 +29,7 @@ public: //------------------------------------------------------------------ RegisterContext (Thread &thread, uint32_t concrete_frame_idx); - virtual - ~RegisterContext (); + ~RegisterContext() override; void InvalidateIfNeeded (bool force); @@ -93,7 +92,7 @@ public: /// /// There may be multiple ways to enumerate the registers for a given /// architecture. ABI references will specify one to be used with - /// DWARF, the register numberings from stabs (aka "gcc"), there may + /// DWARF, the register numberings from process plugin, there may /// be a variation used for eh_frame unwind instructions (e.g. on Darwin), /// and so on. Register 5 by itself is meaningless - RegisterKind /// enumeration tells you what context that number should be translated as. @@ -213,26 +212,27 @@ public: bool WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval); + bool ConvertBetweenRegisterKinds (lldb::RegisterKind source_rk, uint32_t source_regnum, lldb::RegisterKind target_rk, uint32_t& target_regnum); //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ - virtual lldb::TargetSP - CalculateTarget (); + lldb::TargetSP + CalculateTarget() override; - virtual lldb::ProcessSP - CalculateProcess (); + lldb::ProcessSP + CalculateProcess() override; - virtual lldb::ThreadSP - CalculateThread (); + lldb::ThreadSP + CalculateThread() override; - virtual lldb::StackFrameSP - CalculateStackFrame (); + lldb::StackFrameSP + CalculateStackFrame() override; - virtual void - CalculateExecutionContext (ExecutionContext &exe_ctx); + void + CalculateExecutionContext(ExecutionContext &exe_ctx) override; uint32_t GetStopID () const @@ -262,4 +262,4 @@ private: } // namespace lldb_private -#endif // liblldb_RegisterContext_h_ +#endif // liblldb_RegisterContext_h_ diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h index 6a9bbab93c98..5f5d39e2b24b 100644 --- a/include/lldb/Target/SectionLoadList.h +++ b/include/lldb/Target/SectionLoadList.h @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" // Project includes #include "lldb/lldb-public.h" +#include "lldb/Core/Section.h" #include "lldb/Host/Mutex.h" namespace lldb_private { diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h index 95e21445be04..b65b01810176 100644 --- a/include/lldb/Target/StackFrame.h +++ b/include/lldb/Target/StackFrame.h @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/Core/Error.h" @@ -45,11 +47,12 @@ class StackFrame : public: enum ExpressionPathOption { - eExpressionPathOptionCheckPtrVsMember = (1u << 0), - eExpressionPathOptionsNoFragileObjcIvar = (1u << 1), - eExpressionPathOptionsNoSyntheticChildren = (1u << 2), - eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3), - eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4) + eExpressionPathOptionCheckPtrVsMember = (1u << 0), + eExpressionPathOptionsNoFragileObjcIvar = (1u << 1), + eExpressionPathOptionsNoSyntheticChildren = (1u << 2), + eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3), + eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4), + eExpressionPathOptionsInspectAnonymousUnions = (1u << 5) }; //------------------------------------------------------------------ @@ -135,7 +138,7 @@ public: const Address& pc, const SymbolContext *sc_ptr); - virtual ~StackFrame (); + ~StackFrame() override; lldb::ThreadSP GetThread () const @@ -223,7 +226,7 @@ public: /// executing. /// /// @return - /// A pointer to the current Block. NULL is returned if this can + /// A pointer to the current Block. nullptr is returned if this can /// not be provided. //------------------------------------------------------------------ Block * @@ -351,7 +354,7 @@ public: /// Optional string that will be prepended to the frame output description. //------------------------------------------------------------------ void - DumpUsingSettingsFormat (Stream *strm, const char *frame_marker = NULL); + DumpUsingSettingsFormat(Stream *strm, const char *frame_marker = nullptr); //------------------------------------------------------------------ /// Print a description for this frame using a default format. @@ -388,10 +391,10 @@ public: /// Returns true if successful. //------------------------------------------------------------------ bool - GetStatus (Stream &strm, - bool show_frame_info, - bool show_source, - const char *frame_marker = NULL); + GetStatus(Stream &strm, + bool show_frame_info, + bool show_source, + const char *frame_marker = nullptr); //------------------------------------------------------------------ /// Query whether this frame is a concrete frame on the call stack, @@ -465,23 +468,33 @@ public: lldb::ValueObjectSP TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic); + //------------------------------------------------------------------ + /// Query this frame to determine what the default language should be + /// when parsing expressions given the execution context. + /// + /// @return + /// The language of the frame if known, else lldb::eLanguageTypeUnknown. + //------------------------------------------------------------------ + lldb::LanguageType + GetLanguage (); + //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ - virtual lldb::TargetSP - CalculateTarget (); + lldb::TargetSP + CalculateTarget() override; - virtual lldb::ProcessSP - CalculateProcess (); + lldb::ProcessSP + CalculateProcess() override; - virtual lldb::ThreadSP - CalculateThread (); + lldb::ThreadSP + CalculateThread() override; - virtual lldb::StackFrameSP - CalculateStackFrame (); + lldb::StackFrameSP + CalculateStackFrame() override; void - CalculateExecutionContext (ExecutionContext &exe_ctx); + CalculateExecutionContext(ExecutionContext &exe_ctx) override; protected: friend class StackFrameList; @@ -520,9 +533,10 @@ private: ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp StreamString m_disassembly; Mutex m_mutex; + DISALLOW_COPY_AND_ASSIGN (StackFrame); }; } // namespace lldb_private -#endif // liblldb_StackFrame_h_ +#endif // liblldb_StackFrame_h_ diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h index 2680be3e5a68..50a656de9e69 100644 --- a/include/lldb/Target/StackFrameList.h +++ b/include/lldb/Target/StackFrameList.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes @@ -84,15 +85,14 @@ public: GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr); size_t - GetStatus (Stream &strm, - uint32_t first_frame, - uint32_t num_frames, - bool show_frame_info, - uint32_t num_frames_with_source, - const char *frame_marker = NULL); + GetStatus(Stream &strm, + uint32_t first_frame, + uint32_t num_frames, + bool show_frame_info, + uint32_t num_frames_with_source, + const char *frame_marker = nullptr); protected: - friend class Thread; bool @@ -129,9 +129,6 @@ protected: void SetCurrentInlinedDepth (uint32_t new_depth); - //------------------------------------------------------------------ - // Classes that inherit from StackFrameList can see and modify these - //------------------------------------------------------------------ typedef std::vector collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; @@ -147,12 +144,9 @@ protected: bool m_show_inlined_frames; private: - //------------------------------------------------------------------ - // For StackFrameList only - //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN (StackFrameList); }; } // namespace lldb_private -#endif // liblldb_StackFrameList_h_ +#endif // liblldb_StackFrameList_h_ diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h index 75ad8ab38903..aad9d0cfc25c 100644 --- a/include/lldb/Target/StackID.h +++ b/include/lldb/Target/StackID.h @@ -28,7 +28,7 @@ public: StackID () : m_pc (LLDB_INVALID_ADDRESS), m_cfa (LLDB_INVALID_ADDRESS), - m_symbol_scope (NULL) + m_symbol_scope (nullptr) { } @@ -47,9 +47,7 @@ public: { } - ~StackID() - { - } + ~StackID() = default; lldb::addr_t GetPC() const @@ -80,7 +78,7 @@ public: { m_pc = LLDB_INVALID_ADDRESS; m_cfa = LLDB_INVALID_ADDRESS; - m_symbol_scope = NULL; + m_symbol_scope = nullptr; } bool @@ -108,7 +106,6 @@ public: } protected: - friend class StackFrame; void @@ -123,18 +120,15 @@ protected: m_cfa = cfa; } - //------------------------------------------------------------------ - // Classes that inherit from StackID can see and modify these - //------------------------------------------------------------------ lldb::addr_t m_pc; // The pc value for the function/symbol for this frame. This will - // only get used if the symbol scope is NULL (the code where we are + // only get used if the symbol scope is nullptr (the code where we are // stopped is not represented by any function or symbol in any // shared library). lldb::addr_t m_cfa; // The call frame address (stack pointer) value // at the beginning of the function that uniquely // identifies this frame (along with m_symbol_scope below) - SymbolContextScope *m_symbol_scope; // If NULL, there is no block or symbol for this frame. - // If not NULL, this will either be the scope for the + SymbolContextScope *m_symbol_scope; // If nullptr, there is no block or symbol for this frame. + // If not nullptr, this will either be the scope for the // lexical block for the frame, or the scope // for the symbol. Symbol context scopes are // always be unique pointers since the are part @@ -151,4 +145,4 @@ bool operator< (const StackID& lhs, const StackID& rhs); } // namespace lldb_private -#endif // liblldb_StackID_h_ +#endif // liblldb_StackID_h_ diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h index 2553887fa3d9..dfc9860b604a 100644 --- a/include/lldb/Target/StopInfo.h +++ b/include/lldb/Target/StopInfo.h @@ -172,7 +172,7 @@ public: static lldb::StopInfoSP CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp, - lldb::ClangExpressionVariableSP expression_variable_sp); + lldb::ExpressionVariableSP expression_variable_sp); static lldb::StopInfoSP CreateStopReasonWithException (Thread &thread, const char *description); @@ -183,7 +183,7 @@ public: static lldb::ValueObjectSP GetReturnValueObject (lldb::StopInfoSP &stop_info_sp); - static lldb::ClangExpressionVariableSP + static lldb::ExpressionVariableSP GetExpressionVariable (lldb::StopInfoSP &stop_info_sp); protected: diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h index 18f38f79bdbd..54fde88c8d12 100644 --- a/include/lldb/Target/SystemRuntime.h +++ b/include/lldb/Target/SystemRuntime.h @@ -75,8 +75,7 @@ public: /// The destructor is virtual since this class is designed to be /// inherited by the plug-in instance. //------------------------------------------------------------------ - virtual - ~SystemRuntime(); + ~SystemRuntime() override; //------------------------------------------------------------------ /// Called after attaching to a process. @@ -354,9 +353,10 @@ protected: std::vector m_types; private: + DISALLOW_COPY_AND_ASSIGN (SystemRuntime); }; } // namespace lldb_private -#endif // liblldb_SystemRuntime_h_ +#endif // liblldb_SystemRuntime_h_ diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index 427f68e4c5d4..0cdb248a9b44 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -13,6 +13,10 @@ // C Includes // C++ Includes #include +#include +#include +#include +#include // Other libraries and framework includes // Project includes @@ -24,6 +28,8 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/UserSettingsController.h" +#include "lldb/Expression/Expression.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/PathMappingList.h" #include "lldb/Target/ProcessLaunchInfo.h" @@ -55,8 +61,7 @@ class TargetProperties : public Properties public: TargetProperties(Target *target); - virtual - ~TargetProperties(); + ~TargetProperties() override; ArchSpec GetDefaultArchitecture () const; @@ -169,6 +174,9 @@ public: bool GetBreakpointsConsultPlatformAvoidList (); + lldb::LanguageType + GetLanguage () const; + const char * GetExpressionPrefixContentsAsCString (); @@ -229,7 +237,6 @@ private: static void DisableASLRValueChangedCallback(void *target_property_ptr, OptionValue *); static void DisableSTDIOValueChangedCallback(void *target_property_ptr, OptionValue *); -private: //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ @@ -295,9 +302,7 @@ public: const char * GetPrefix () const { - if (m_prefix.empty()) - return NULL; - return m_prefix.c_str(); + return (m_prefix.empty() ? nullptr : m_prefix.c_str()); } void @@ -437,6 +442,18 @@ public: m_generate_debug_info = b; } + bool + GetColorizeErrors () const + { + return m_ansi_color_errors; + } + + void + SetColorizeErrors (bool b) + { + m_ansi_color_errors = b; + } + bool GetTrapExceptions() const { @@ -449,6 +466,18 @@ public: m_trap_exceptions = b; } + bool + GetREPLEnabled() const + { + return m_repl; + } + + void + SetREPLEnabled (bool b) + { + m_repl = b; + } + void SetCancelCallback (lldb::ExpressionCancelCallback callback, void *baton) { @@ -459,10 +488,36 @@ public: bool InvokeCancelCallback (lldb::ExpressionEvaluationPhase phase) const { - if (m_cancel_callback == nullptr) - return false; + return ((m_cancel_callback != nullptr) ? m_cancel_callback(phase, m_cancel_callback_baton) : false); + } + + // Allows the expression contents to be remapped to point to the specified file and line + // using #line directives. + void + SetPoundLine (const char *path, uint32_t line) const + { + if (path && path[0]) + { + m_pound_line_file = path; + m_pound_line_line = line; + } else - return m_cancel_callback (phase, m_cancel_callback_baton); + { + m_pound_line_file.clear(); + m_pound_line_line = 0; + } + } + + const char * + GetPoundLineFilePath () const + { + return (m_pound_line_file.empty() ? nullptr : m_pound_line_file.c_str()); + } + + uint32_t + GetPoundLineLine () const + { + return m_pound_line_line; } void @@ -489,13 +544,20 @@ private: bool m_stop_others; bool m_debug; bool m_trap_exceptions; + bool m_repl; bool m_generate_debug_info; + bool m_ansi_color_errors; bool m_result_is_internal; lldb::DynamicValueType m_use_dynamic; uint32_t m_timeout_usec; uint32_t m_one_thread_timeout_usec; lldb::ExpressionCancelCallback m_cancel_callback; void *m_cancel_callback_baton; + // If m_pound_line_file is not empty and m_pound_line_line is non-zero, + // use #line %u "%s" before the expression content to remap where the source + // originates + mutable std::string m_pound_line_file; + mutable uint32_t m_pound_line_line; }; //---------------------------------------------------------------------- @@ -527,7 +589,7 @@ public: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } @@ -540,20 +602,19 @@ public: TargetEventData (const lldb::TargetSP &target_sp, const ModuleList &module_list); - virtual - ~TargetEventData(); + ~TargetEventData() override; static const ConstString & GetFlavorString (); - virtual const ConstString & - GetFlavor () const + const ConstString & + GetFlavor() const override { return TargetEventData::GetFlavorString (); } - virtual void - Dump (Stream *s) const; + void + Dump(Stream *s) const override; static const TargetEventData * GetEventDataFromEvent (const Event *event_ptr); @@ -583,6 +644,8 @@ public: DISALLOW_COPY_AND_ASSIGN (TargetEventData); }; + ~Target() override; + static void SettingsInitialize (); @@ -608,8 +671,8 @@ public: // UpdateInstanceName (); lldb::ModuleSP - GetSharedModule (const ModuleSpec &module_spec, - Error *error_ptr = NULL); + GetSharedModule(const ModuleSpec &module_spec, + Error *error_ptr = nullptr); //---------------------------------------------------------------------- // Settings accessors @@ -618,36 +681,6 @@ public: static const lldb::TargetPropertiesSP & GetGlobalProperties(); - -private: - //------------------------------------------------------------------ - /// Construct with optional file and arch. - /// - /// This member is private. Clients must use - /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*) - /// so all targets can be tracked from the central target list. - /// - /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*) - //------------------------------------------------------------------ - Target (Debugger &debugger, - const ArchSpec &target_arch, - const lldb::PlatformSP &platform_sp, - bool is_dummy_target); - - // Helper function. - bool - ProcessIsValid (); - - // Copy breakpoints, stop hooks and so forth from the dummy target: - void - PrimeFromDummyTarget(Target *dummy_target); - - void - AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal); - -public: - ~Target(); - Mutex & GetAPIMutex () { @@ -659,6 +692,7 @@ public: void CleanupProcess (); + //------------------------------------------------------------------ /// Dump a description of this object to a Stream. /// @@ -718,7 +752,7 @@ public: lldb::BreakpointSP GetBreakpointByID (lldb::break_id_t break_id); - // Use this to create a file and line breakpoint to a given module or all module it is NULL + // Use this to create a file and line breakpoint to a given module or all module it is nullptr lldb::BreakpointSP CreateBreakpoint (const FileSpecList *containingModules, const FileSpec &file, @@ -744,24 +778,32 @@ public: bool internal, bool request_hardware); + // Use this to create a breakpoint from a load address and a module file spec + lldb::BreakpointSP + CreateAddressInModuleBreakpoint (lldb::addr_t file_addr, + bool internal, + const FileSpec *file_spec, + bool request_hardware); + // Use this to create Address breakpoints: lldb::BreakpointSP - CreateBreakpoint (Address &addr, + CreateBreakpoint (const Address &addr, bool internal, bool request_hardware); - // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL + // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is nullptr // When "skip_prologue is set to eLazyBoolCalculate, we use the current target // setting, else we use the values passed in lldb::BreakpointSP CreateFuncRegexBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, RegularExpression &func_regexp, + lldb::LanguageType requested_language, LazyBool skip_prologue, bool internal, bool request_hardware); - // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL + // Use this to create a function breakpoint by name in containingModule, or all modules if it is nullptr // When "skip_prologue is set to 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. @@ -770,17 +812,18 @@ public: const FileSpecList *containingSourceFiles, const char *func_name, uint32_t func_name_type_mask, + lldb::LanguageType language, LazyBool skip_prologue, bool internal, bool request_hardware); lldb::BreakpointSP - CreateExceptionBreakpoint (enum lldb::LanguageType language, - bool catch_bp, - bool throw_bp, - bool internal, - Args *additional_args = nullptr, - Error *additional_args_error = nullptr); + CreateExceptionBreakpoint(enum lldb::LanguageType language, + bool catch_bp, + bool throw_bp, + bool internal, + Args *additional_args = nullptr, + Error *additional_args_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 @@ -792,6 +835,7 @@ public: const char *func_names[], size_t num_names, uint32_t func_name_type_mask, + lldb::LanguageType language, LazyBool skip_prologue, bool internal, bool request_hardware); @@ -801,11 +845,11 @@ public: const FileSpecList *containingSourceFiles, const std::vector &func_names, uint32_t func_name_type_mask, + lldb::LanguageType language, LazyBool skip_prologue, bool internal, bool request_hardware); - // Use this to create a general breakpoint: lldb::BreakpointSP CreateBreakpoint (lldb::SearchFilterSP &filter_sp, @@ -818,7 +862,7 @@ public: lldb::WatchpointSP CreateWatchpoint (lldb::addr_t addr, size_t size, - const ClangASTType *type, + const CompilerType *type, uint32_t kind, Error &error); @@ -914,26 +958,14 @@ public: lldb::addr_t GetOpcodeLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; -protected: - //------------------------------------------------------------------ - /// Implementing of ModuleList::Notifier. - //------------------------------------------------------------------ - - virtual void - ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp); - - virtual void - ModuleRemoved (const ModuleList& module_list, const lldb::ModuleSP& module_sp); - - virtual void - ModuleUpdated (const ModuleList& module_list, - const lldb::ModuleSP& old_module_sp, - const lldb::ModuleSP& new_module_sp); - virtual void - WillClearList (const ModuleList& module_list); + // 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. + lldb::addr_t + GetBreakableLoadAddress (lldb::addr_t addr); -public: - void ModulesDidLoad (ModuleList &module_list); @@ -970,7 +1002,7 @@ public: /// /// @return /// The shared pointer to the executable module which can - /// contains a NULL Module object if no executable has been + /// contains a nullptr Module object if no executable has been /// set. /// /// @see DynamicLoader @@ -1014,9 +1046,9 @@ public: SetExecutableModule (lldb::ModuleSP& module_sp, bool get_dependent_files); bool - LoadScriptingResources (std::list& errors, - Stream* feedback_stream = NULL, - bool continue_on_error = true) + LoadScriptingResources(std::list& errors, + Stream* feedback_stream = nullptr, + bool continue_on_error = true) { return m_images.LoadScriptingResourcesInTarget(this,errors,feedback_stream,continue_on_error); } @@ -1146,12 +1178,12 @@ public: // 2 - if there is a valid process, try and read from its memory // 3 - if (prefer_file_cache == false) then read from object file cache size_t - ReadMemory (const Address& addr, - bool prefer_file_cache, - void *dst, - size_t dst_len, - Error &error, - lldb::addr_t *load_addr_ptr = NULL); + ReadMemory(const Address& addr, + bool prefer_file_cache, + void *dst, + size_t dst_len, + Error &error, + lldb::addr_t *load_addr_ptr = nullptr); size_t ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error); @@ -1199,28 +1231,70 @@ public: //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ - virtual lldb::TargetSP - CalculateTarget (); + lldb::TargetSP + CalculateTarget() override; - virtual lldb::ProcessSP - CalculateProcess (); + lldb::ProcessSP + CalculateProcess() override; - virtual lldb::ThreadSP - CalculateThread (); + lldb::ThreadSP + CalculateThread() override; - virtual lldb::StackFrameSP - CalculateStackFrame (); + lldb::StackFrameSP + CalculateStackFrame() override; - virtual void - CalculateExecutionContext (ExecutionContext &exe_ctx); + void + CalculateExecutionContext(ExecutionContext &exe_ctx) override; PathMappingList & GetImageSearchPathList (); + TypeSystem * + GetScratchTypeSystemForLanguage (Error *error, lldb::LanguageType language, bool create_on_demand = true); + + PersistentExpressionState * + GetPersistentExpressionStateForLanguage (lldb::LanguageType language); + + // Creates a UserExpression for the given language, the rest of the parameters have the + // same meaning as for the UserExpression constructor. + // Returns a new-ed object which the caller owns. + + UserExpression * + GetUserExpressionForLanguage(const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options, + Error &error); + + // Creates a FunctionCaller for the given language, the rest of the parameters have the + // same meaning as for the FunctionCaller constructor. Since a FunctionCaller can't be + // IR Interpreted, it makes no sense to call this with an ExecutionContextScope that lacks + // a Process. + // Returns a new-ed object which the caller owns. + + FunctionCaller * + GetFunctionCallerForLanguage (lldb::LanguageType language, + const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name, + Error &error); + + // Creates a UtilityFunction for the given language, the rest of the parameters have the + // same meaning as for the UtilityFunction constructor. + // Returns a new-ed object which the caller owns. + + UtilityFunction * + GetUtilityFunctionForLanguage (const char *expr, + lldb::LanguageType language, + const char *name, + Error &error); + ClangASTContext * GetScratchClangASTContext(bool create_on_demand=true); - ClangASTImporter * + lldb::ClangASTImporterSP GetClangASTImporter(); //---------------------------------------------------------------------- @@ -1266,23 +1340,26 @@ public: // in in th execution context. lldb::ExpressionResults EvaluateExpression (const char *expression, - StackFrame *frame, + ExecutionContextScope *exe_scope, lldb::ValueObjectSP &result_valobj_sp, const EvaluateExpressionOptions& options = EvaluateExpressionOptions()); - ClangPersistentVariables & - GetPersistentVariables(); - + lldb::ExpressionVariableSP + GetPersistentVariable(const ConstString &name); + + lldb::addr_t + GetPersistentSymbol(const ConstString &name); + //------------------------------------------------------------------ // Target Stop Hooks //------------------------------------------------------------------ class StopHook : public UserID { public: - ~StopHook (); - StopHook (const StopHook &rhs); - + + ~StopHook (); + StringList * GetCommandPointer () { @@ -1448,8 +1525,31 @@ public: lldb::SearchFilterSP GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles); + + lldb::REPLSP + GetREPL (Error &err, lldb::LanguageType language, const char *repl_options, bool can_create); + + void + SetREPL (lldb::LanguageType language, lldb::REPLSP repl_sp); protected: + //------------------------------------------------------------------ + /// Implementing of ModuleList::Notifier. + //------------------------------------------------------------------ + + void + ModuleAdded(const ModuleList& module_list, const lldb::ModuleSP& module_sp) override; + + void + ModuleRemoved(const ModuleList& module_list, const lldb::ModuleSP& module_sp) override; + + void + ModuleUpdated(const ModuleList& module_list, + const lldb::ModuleSP& old_module_sp, + const lldb::ModuleSP& new_module_sp) override; + void + WillClearList(const ModuleList& module_list) override; + //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ @@ -1470,11 +1570,13 @@ protected: lldb::ProcessSP m_process_sp; lldb::SearchFilterSP m_search_filter_sp; PathMappingList m_image_search_paths; - lldb::ClangASTContextUP m_scratch_ast_context_ap; - lldb::ClangASTSourceUP m_scratch_ast_source_ap; - lldb::ClangASTImporterUP m_ast_importer_ap; + TypeSystemMap m_scratch_type_system_map; + + typedef std::map REPLMap; + REPLMap m_repl_map; + + lldb::ClangASTImporterSP m_ast_importer_sp; lldb::ClangModulesDeclVendorUP m_clang_modules_decl_vendor_ap; - lldb::ClangPersistentVariablesUP m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. lldb::SourceManagerUP m_source_manager_ap; @@ -1490,9 +1592,34 @@ protected: void *baton); private: + //------------------------------------------------------------------ + /// Construct with optional file and arch. + /// + /// This member is private. Clients must use + /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*) + /// so all targets can be tracked from the central target list. + /// + /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*) + //------------------------------------------------------------------ + Target (Debugger &debugger, + const ArchSpec &target_arch, + const lldb::PlatformSP &platform_sp, + bool is_dummy_target); + + // Helper function. + bool + ProcessIsValid (); + + // Copy breakpoints, stop hooks and so forth from the dummy target: + void + PrimeFromDummyTarget(Target *dummy_target); + + void + AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal); + DISALLOW_COPY_AND_ASSIGN (Target); }; } // namespace lldb_private -#endif // liblldb_Target_h_ +#endif // liblldb_Target_h_ diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h index 27e46ba81a70..fddb715b46f3 100644 --- a/include/lldb/Target/TargetList.h +++ b/include/lldb/Target/TargetList.h @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/Core/Broadcaster.h" @@ -37,7 +39,6 @@ private: TargetList(Debugger &debugger); public: - //------------------------------------------------------------------ /// Broadcaster event bits definitions. //------------------------------------------------------------------ @@ -51,12 +52,12 @@ public: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } - virtual ~TargetList(); + ~TargetList() override; //------------------------------------------------------------------ /// Create a new Target. @@ -72,12 +73,12 @@ public: /// /// @param[in] file_spec /// The main executable file for a debug target. This value - /// can be NULL and the file can be set later using: + /// can be nullptr and the file can be set later using: /// Target::SetExecutableModule (ModuleSP&) /// /// @param[in] triple_cstr /// A target triple string to be used for the target. This can - /// be NULL if the triple is not known or when attaching to a + /// be nullptr if the triple is not known or when attaching to a /// process. /// /// @param[in] get_dependent_modules @@ -86,7 +87,7 @@ public: /// /// @param[in] platform_options /// A pointer to the platform options to use when creating this - /// target. If this value is NULL, then the currently selected + /// target. If this value is nullptr, then the currently selected /// platform will be used. /// /// @param[out] target_sp @@ -149,7 +150,7 @@ public: //------------------------------------------------------------------ /// Find the target that contains has an executable whose path /// matches \a exe_file_spec, and whose architecture matches - /// \a arch_ptr if arch_ptr is not NULL. + /// \a arch_ptr if arch_ptr is not nullptr. /// /// @param[in] exe_file_spec /// A file spec containing a basename, or a full path (directory @@ -160,18 +161,18 @@ public: /// directory, then both must match. /// /// @param[in] exe_arch_ptr - /// If not NULL then the architecture also needs to match, else + /// If not nullptr then the architecture also needs to match, else /// the architectures will be compared. /// /// @return /// A shared pointer to a target object. The returned shared - /// pointer will contain NULL if no target objects have a + /// pointer will contain nullptr if no target objects have a /// executable whose full or partial path matches /// with a matching process ID. //------------------------------------------------------------------ lldb::TargetSP - FindTargetWithExecutableAndArchitecture (const FileSpec &exe_file_spec, - const ArchSpec *exe_arch_ptr = NULL) const; + FindTargetWithExecutableAndArchitecture(const FileSpec &exe_file_spec, + const ArchSpec *exe_arch_ptr = nullptr) const; //------------------------------------------------------------------ /// Find the target that contains a process with process ID \a @@ -182,7 +183,7 @@ public: /// /// @return /// A shared pointer to a target object. The returned shared - /// pointer will contain NULL if no target objects own a process + /// pointer will contain nullptr if no target objects own a process /// with a matching process ID. //------------------------------------------------------------------ lldb::TargetSP @@ -230,6 +231,7 @@ protected: lldb::TargetSP m_dummy_target_sp; mutable Mutex m_target_list_mutex; uint32_t m_selected_target_idx; + private: lldb::TargetSP GetDummyTarget (lldb_private::Debugger &debugger); @@ -262,4 +264,4 @@ private: } // namespace lldb_private -#endif // liblldb_TargetList_h_ +#endif // liblldb_TargetList_h_ diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index c6a3c8e9851a..7aff77bd16f4 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -10,6 +10,14 @@ #ifndef liblldb_Thread_h_ #define liblldb_Thread_h_ +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/Mutex.h" #include "lldb/Core/Broadcaster.h" @@ -30,8 +38,7 @@ class ThreadProperties : public Properties public: ThreadProperties(bool is_global); - virtual - ~ThreadProperties(); + ~ThreadProperties() override; //------------------------------------------------------------------ /// The regular expression returned determines symbols that this @@ -39,7 +46,7 @@ public: /// /// @return /// A pointer to a regular expression to compare against symbols, - /// or NULL if all symbols are allowed. + /// or nullptr if all symbols are allowed. /// //------------------------------------------------------------------ const RegularExpression * @@ -82,7 +89,7 @@ public: static ConstString &GetStaticBroadcasterClass (); - virtual ConstString &GetBroadcasterClass() const + ConstString &GetBroadcasterClass() const override { return GetStaticBroadcasterClass(); } @@ -97,19 +104,19 @@ public: ThreadEventData(); - virtual ~ThreadEventData(); + ~ThreadEventData() override; static const ConstString & GetFlavorString (); - virtual const ConstString & - GetFlavor () const + const ConstString & + GetFlavor() const override { return ThreadEventData::GetFlavorString (); } - virtual void - Dump (Stream *s) const; + void + Dump(Stream *s) const override; static const ThreadEventData * GetEventDataFromEvent (const Event *event_ptr); @@ -138,9 +145,9 @@ public: private: lldb::ThreadSP m_thread_sp; StackID m_stack_id; - DISALLOW_COPY_AND_ASSIGN (ThreadEventData); + + DISALLOW_COPY_AND_ASSIGN (ThreadEventData); }; - struct ThreadStateCheckpoint { @@ -151,15 +158,6 @@ public: lldb::addr_t current_inlined_pc; }; - static void - SettingsInitialize (); - - static void - SettingsTerminate (); - - static const ThreadPropertiesSP & - GetGlobalProperties(); - //------------------------------------------------------------------ /// Constructor /// @@ -179,7 +177,16 @@ public: //------------------------------------------------------------------ Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id = false); - virtual ~Thread(); + ~Thread() override; + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + + static const ThreadPropertiesSP & + GetGlobalProperties(); lldb::ProcessSP GetProcess() const @@ -303,6 +310,9 @@ public: lldb::StopReason GetStopReason(); + bool + StopInfoIsUpToDate() const; + // This sets the stop reason to a "blank" stop reason, so you can call functions on the thread // without having the called function run with whatever stop reason you stopped with. void @@ -320,7 +330,7 @@ public: virtual const char * GetInfo () { - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -348,7 +358,7 @@ public: virtual const char * GetName () { - return NULL; + return nullptr; } virtual void @@ -390,12 +400,12 @@ public: /// /// @return /// The Queue name, if the Thread subclass implements this, else - /// NULL. + /// nullptr. //------------------------------------------------------------------ virtual const char * GetQueueName () { - return NULL; + return nullptr; } virtual void @@ -475,7 +485,7 @@ public: ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false); Error - JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = NULL); + JumpToLine(const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = nullptr); virtual lldb::StackFrameSP GetFrameWithStackID (const StackID &stack_id) @@ -492,16 +502,11 @@ public: } lldb::StackFrameSP - GetSelectedFrame () - { - lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList()); - return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex()); - } + GetSelectedFrame (); uint32_t SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false); - bool SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false); @@ -608,6 +613,7 @@ public: //------------------------------------------------------------------ virtual Error StepOut (); + //------------------------------------------------------------------ /// Retrieves the per-thread data area. /// Most OSs maintain a per-thread pointer (e.g. the FS register on @@ -684,7 +690,7 @@ public: /// Otherwise this plan will go on the end of the plan stack. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued. //------------------------------------------------------------------ virtual lldb::ThreadPlanSP QueueFundamentalPlan (bool abort_other_plans); @@ -703,7 +709,7 @@ public: /// \b true if we will stop other threads while we single step this one. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// 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, @@ -739,7 +745,7 @@ public: /// If eLazyBoolCalculate, we will consult the default set in the thread. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued. //------------------------------------------------------------------ virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange (bool abort_other_plans, @@ -748,6 +754,15 @@ public: lldb::RunMode stop_other_threads, LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); + // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple + // LineEntries of the same source line number to step over a longer address range in a single operation. + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepOverRange (bool abort_other_plans, + const LineEntry &line_entry, + const SymbolContext &addr_context, + lldb::RunMode stop_other_threads, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); + //------------------------------------------------------------------ /// Queues the plan used to step through an address range, stepping into functions. /// @@ -783,7 +798,7 @@ public: /// If eLazyBoolCalculate, it will consult the default set in the thread. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued. //------------------------------------------------------------------ virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange (bool abort_other_plans, @@ -794,6 +809,17 @@ public: LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); + // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple + // LineEntries of the same source line number to step over a longer address range in a single operation. + 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, + LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, + LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); + //------------------------------------------------------------------ /// Queue the plan used to step out of the function at the current PC of /// \a thread. @@ -824,7 +850,7 @@ public: /// If eLazyBoolCalculate, it will consult the default set in the thread. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued. //------------------------------------------------------------------ virtual lldb::ThreadPlanSP QueueThreadPlanForStepOut (bool abort_other_plans, @@ -863,7 +889,7 @@ public: /// See standard meanings for the stop & run votes in ThreadPlan.h. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// A shared pointer to the newly queued thread plan, or nullptr if the plan could not be queued. //------------------------------------------------------------------ virtual lldb::ThreadPlanSP QueueThreadPlanForStepOutNoShouldStop (bool abort_other_plans, @@ -891,7 +917,7 @@ public: /// \b true if we will stop other threads while we single step this one. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// 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, @@ -914,7 +940,7 @@ public: /// \b true if we will stop other threads while we single step this one. /// /// @return - /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + /// 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, @@ -957,15 +983,6 @@ public: Error UnwindInnermostExpression(); -private: - bool - PlanIsBasePlan (ThreadPlan *plan_ptr); - - void - BroadcastSelectedFrameChange(StackID &new_frame_id); - -public: - //------------------------------------------------------------------ /// Gets the outer-most plan that was popped off the plan stack in the /// most recent stop. Useful for printing the stop reason accurately. @@ -990,11 +1007,11 @@ public: /// Gets the outer-most expression variable from the completed plans /// /// @return - /// A ClangExpressionVariableSP, either empty if there is no + /// A ExpressionVariableSP, either empty if there is no /// plan completed an expression during the current stop /// or the expression variable that was made for the completed expression. //------------------------------------------------------------------ - lldb::ClangExpressionVariableSP + lldb::ExpressionVariableSP GetExpressionVariable (); //------------------------------------------------------------------ @@ -1041,7 +1058,6 @@ public: void QueueThreadPlan (lldb::ThreadPlanSP &plan_sp, bool abort_other_plans); - //------------------------------------------------------------------ /// Discards the plans queued on the plan stack of the current thread. This is /// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call. @@ -1147,20 +1163,20 @@ public: //------------------------------------------------------------------ // lldb::ExecutionContextScope pure virtual functions //------------------------------------------------------------------ - virtual lldb::TargetSP - CalculateTarget (); + lldb::TargetSP + CalculateTarget() override; - virtual lldb::ProcessSP - CalculateProcess (); + lldb::ProcessSP + CalculateProcess() override; - virtual lldb::ThreadSP - CalculateThread (); + lldb::ThreadSP + CalculateThread() override; - virtual lldb::StackFrameSP - CalculateStackFrame (); + lldb::StackFrameSP + CalculateStackFrame() override; - virtual void - CalculateExecutionContext (ExecutionContext &exe_ctx); + void + CalculateExecutionContext(ExecutionContext &exe_ctx) override; lldb::StackFrameSP GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr); @@ -1271,7 +1287,6 @@ public: } protected: - friend class ThreadPlan; friend class ThreadList; friend class ThreadEventData; @@ -1323,7 +1338,15 @@ protected: lldb::StackFrameListSP GetStackFrameList (); - + + void + SetTemporaryResumeState(lldb::StateType new_state) + { + m_temporary_resume_state = new_state; + } + + void + FunctionOptimizationWarning (lldb_private::StackFrame *frame); //------------------------------------------------------------------ // Classes that inherit from Process can see and modify these @@ -1353,14 +1376,17 @@ protected: private: bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info for this thread? StructuredData::ObjectSP m_extended_info; // The extended info for this thread - //------------------------------------------------------------------ - // For Thread only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (Thread); +private: + bool + PlanIsBasePlan (ThreadPlan *plan_ptr); + void + BroadcastSelectedFrameChange(StackID &new_frame_id); + + DISALLOW_COPY_AND_ASSIGN (Thread); }; } // namespace lldb_private -#endif // liblldb_Thread_h_ +#endif // liblldb_Thread_h_ diff --git a/include/lldb/Target/ThreadList.h b/include/lldb/Target/ThreadList.h index 12c430c9c8d8..e6489b25e558 100644 --- a/include/lldb/Target/ThreadList.h +++ b/include/lldb/Target/ThreadList.h @@ -32,8 +32,7 @@ public: ThreadList (const ThreadList &rhs); - virtual - ~ThreadList (); + ~ThreadList() override; const ThreadList& operator = (const ThreadList& rhs); @@ -128,8 +127,8 @@ public: void SetStopID (uint32_t stop_id); - virtual Mutex & - GetMutex (); + Mutex & + GetMutex() override; void Update (ThreadList &rhs); @@ -150,9 +149,10 @@ protected: lldb::tid_t m_selected_tid; ///< For targets that need the notion of a current thread. private: + ThreadList (); }; } // namespace lldb_private -#endif // liblldb_ThreadList_h_ +#endif // liblldb_ThreadList_h_ diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h index db2e79894057..e6f9aeb78dd6 100644 --- a/include/lldb/Target/ThreadPlan.h +++ b/include/lldb/Target/ThreadPlan.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -518,10 +519,10 @@ public: // the user regained control at that point) a subsequent process control command step/continue/etc. might // complete the expression evaluations. If so, the result of the expression evaluation will show up here. - virtual lldb::ClangExpressionVariableSP + virtual lldb::ExpressionVariableSP GetExpressionVariable () { - return lldb::ClangExpressionVariableSP(); + return lldb::ExpressionVariableSP(); } // If a thread plan stores the state before it was run, then you might @@ -562,13 +563,14 @@ public: else return m_iteration_count; } + protected: //------------------------------------------------------------------ // Classes that inherit from ThreadPlan can see and modify these //------------------------------------------------------------------ virtual bool - DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; }; + DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; } virtual bool DoPlanExplainsStop (Event *event_ptr) = 0; @@ -613,6 +615,9 @@ protected: virtual lldb::StateType GetPlanRunState () = 0; + bool + IsUsuallyUnexplainedStopReason(lldb::StopReason); + Thread &m_thread; Vote m_stop_vote; Vote m_run_vote; @@ -653,47 +658,46 @@ class ThreadPlanNull : public ThreadPlan { public: ThreadPlanNull (Thread &thread); - virtual ~ThreadPlanNull (); + ~ThreadPlanNull() override; - virtual void - GetDescription (Stream *s, - lldb::DescriptionLevel level); + void + GetDescription(Stream *s, + lldb::DescriptionLevel level) override; - virtual bool - ValidatePlan (Stream *error); + bool + ValidatePlan(Stream *error) override; - virtual bool - ShouldStop (Event *event_ptr); + bool + ShouldStop(Event *event_ptr) override; - virtual bool - MischiefManaged (); + bool + MischiefManaged() override; - virtual bool - WillStop (); + bool + WillStop() override; - virtual bool - IsBasePlan() + bool + IsBasePlan() override { return true; } - virtual bool - OkayToDiscard () + bool + OkayToDiscard() override { return false; } protected: - virtual bool - DoPlanExplainsStop (Event *event_ptr); + bool + DoPlanExplainsStop(Event *event_ptr) override; - virtual lldb::StateType - GetPlanRunState (); + lldb::StateType + GetPlanRunState() override; DISALLOW_COPY_AND_ASSIGN(ThreadPlanNull); }; - } // namespace lldb_private -#endif // liblldb_ThreadPlan_h_ +#endif // liblldb_ThreadPlan_h_ diff --git a/include/lldb/Target/ThreadPlanBase.h b/include/lldb/Target/ThreadPlanBase.h index 69959e12f848..a0d30b5f0b67 100644 --- a/include/lldb/Target/ThreadPlanBase.h +++ b/include/lldb/Target/ThreadPlanBase.h @@ -31,31 +31,32 @@ class ThreadPlanBase : public ThreadPlan { friend class Process; // RunThreadPlan manages "stopper" base plans. public: - virtual ~ThreadPlanBase (); + ~ThreadPlanBase() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual Vote ShouldReportStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + Vote ShouldReportStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; - virtual bool OkayToDiscard() + bool + OkayToDiscard() override { return false; } - virtual bool - IsBasePlan() + bool + IsBasePlan() override { return true; } protected: - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); - virtual bool DoPlanExplainsStop (Event *event_ptr); + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; + bool DoPlanExplainsStop(Event *event_ptr) override; ThreadPlanBase (Thread &thread); private: @@ -65,7 +66,6 @@ private: DISALLOW_COPY_AND_ASSIGN (ThreadPlanBase); }; - } // namespace lldb_private -#endif // liblldb_ThreadPlanFundamental_h_ +#endif // liblldb_ThreadPlanFundamental_h_ diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h index 36e4d6e71c79..47eee2808f1e 100644 --- a/include/lldb/Target/ThreadPlanCallFunction.h +++ b/include/lldb/Target/ThreadPlanCallFunction.h @@ -26,11 +26,11 @@ class ThreadPlanCallFunction : public ThreadPlan { // Create a thread plan to call a function at the address passed in the "function" // argument. If you plan to call GetReturnValueObject, then pass in the - // return type, otherwise just pass in an invalid ClangASTType. + // return type, otherwise just pass in an invalid CompilerType. public: ThreadPlanCallFunction (Thread &thread, const Address &function, - const ClangASTType &return_type, + const CompilerType &return_type, llvm::ArrayRef args, const EvaluateExpressionOptions &options); @@ -38,35 +38,34 @@ public: const Address &function, const EvaluateExpressionOptions &options); - virtual - ~ThreadPlanCallFunction (); + ~ThreadPlanCallFunction() override; - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level); + void + GetDescription(Stream *s, lldb::DescriptionLevel level) override; - virtual bool - ValidatePlan (Stream *error); + bool + ValidatePlan(Stream *error) override; - virtual bool - ShouldStop (Event *event_ptr); + bool + ShouldStop(Event *event_ptr) override; - virtual Vote - ShouldReportStop(Event *event_ptr); + Vote + ShouldReportStop(Event *event_ptr) override; - virtual bool - StopOthers (); + bool + StopOthers() override; - virtual lldb::StateType - GetPlanRunState (); + lldb::StateType + GetPlanRunState() override; - virtual void - DidPush (); + void + DidPush() override; - virtual bool - WillStop (); + bool + WillStop() override; - virtual bool - MischiefManaged (); + bool + MischiefManaged() override; // To get the return value from a function call you must create a // lldb::ValueSP that contains a valid clang type in its context and call @@ -77,8 +76,8 @@ public: // plan is complete, you can call "GetReturnValue()" to retrieve the value // that was extracted. - virtual lldb::ValueObjectSP - GetReturnValueObject () + lldb::ValueObjectSP + GetReturnValueObject() override { return m_return_valobj_sp; } @@ -93,11 +92,11 @@ public: return m_function_sp; } - // Classes that derive from ClangFunction, and implement + // Classes that derive from FunctionCaller, and implement // their own WillPop methods should call this so that the // thread state gets restored if the plan gets discarded. - virtual void - WillPop (); + void + WillPop() override; // If the thread plan stops mid-course, this will be the stop reason that interrupted us. // Once DoTakedown is called, this will be the real stop reason at the end of the function call. @@ -105,8 +104,8 @@ public: // This is needed because we want the CallFunction thread plans not to show up as the stop reason. // But if something bad goes wrong, it is nice to be able to tell the user what really happened. - virtual lldb::StopInfoSP - GetRealStopInfo() + lldb::StopInfoSP + GetRealStopInfo() override { if (m_real_stop_info_sp) return m_real_stop_info_sp; @@ -120,23 +119,23 @@ public: return m_stop_address; } - virtual bool - RestoreThreadState(); + bool + RestoreThreadState() override; - virtual void - ThreadDestroyed () + void + ThreadDestroyed() override { m_takedown_done = true; } - virtual void - SetStopOthers (bool new_value); + void + SetStopOthers(bool new_value) override; protected: void ReportRegisterState (const char *message); - virtual bool - DoPlanExplainsStop (Event *event_ptr); + bool + DoPlanExplainsStop(Event *event_ptr) override; virtual void SetReturnValue(); @@ -184,10 +183,10 @@ protected: lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown; private: - ClangASTType m_return_type; + CompilerType m_return_type; DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction); }; } // namespace lldb_private -#endif // liblldb_ThreadPlanCallFunction_h_ +#endif // liblldb_ThreadPlanCallFunction_h_ diff --git a/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h b/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h index 83d78a5dca08..529057175287 100644 --- a/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h +++ b/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h @@ -38,7 +38,7 @@ public: llvm::ArrayRef args, const EvaluateExpressionOptions &options); - ~ThreadPlanCallFunctionUsingABI (); + ~ThreadPlanCallFunctionUsingABI() override; void GetDescription (Stream *s, lldb::DescriptionLevel level) override; @@ -47,7 +47,6 @@ protected: void SetReturnValue () override; - private: llvm::Type &m_return_type; DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunctionUsingABI); @@ -55,4 +54,4 @@ private: } // namespace lldb_private -#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_ +#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_ diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h index e40762c928b5..bb261d9c96b4 100644 --- a/include/lldb/Target/ThreadPlanCallUserExpression.h +++ b/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -30,22 +30,21 @@ public: Address &function, llvm::ArrayRef args, const EvaluateExpressionOptions &options, - lldb::ClangUserExpressionSP &user_expression_sp); + lldb::UserExpressionSP &user_expression_sp); - virtual - ~ThreadPlanCallUserExpression (); + ~ThreadPlanCallUserExpression() override; - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level); + void + GetDescription(Stream *s, lldb::DescriptionLevel level) override; - virtual void - WillPop (); + void + WillPop() override; - virtual lldb::StopInfoSP - GetRealStopInfo(); + lldb::StopInfoSP + GetRealStopInfo() override; - virtual bool - MischiefManaged (); + bool + MischiefManaged() override; void TransferExpressionOwnership () @@ -53,19 +52,19 @@ public: m_manage_materialization = true; } - virtual lldb::ClangExpressionVariableSP - GetExpressionVariable () + lldb::ExpressionVariableSP + GetExpressionVariable() override { return m_result_var_sp; } protected: private: - lldb::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the + lldb::UserExpressionSP m_user_expression_sp; // This is currently just used to ensure the // User expression the initiated this ThreadPlan // lives as long as the thread plan does. bool m_manage_materialization = false; - lldb::ClangExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization, + lldb::ExpressionVariableSP m_result_var_sp; // If we are left to manage the materialization, // then stuff the result expression variable here. DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression); @@ -73,4 +72,4 @@ private: } // namespace lldb_private -#endif // liblldb_ThreadPlanCallUserExpression_h_ +#endif // liblldb_ThreadPlanCallUserExpression_h_ diff --git a/include/lldb/Target/ThreadPlanPython.h b/include/lldb/Target/ThreadPlanPython.h index ffcee018a5fb..ab3fbbdf6fb5 100644 --- a/include/lldb/Target/ThreadPlanPython.h +++ b/include/lldb/Target/ThreadPlanPython.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" @@ -37,45 +38,44 @@ class ThreadPlanPython : public ThreadPlan { public: ThreadPlanPython (Thread &thread, const char *class_name); - virtual ~ThreadPlanPython (); + ~ThreadPlanPython() override; - virtual void - GetDescription (Stream *s, - lldb::DescriptionLevel level); + void + GetDescription(Stream *s, + lldb::DescriptionLevel level) override; - virtual bool - ValidatePlan (Stream *error); + bool + ValidatePlan(Stream *error) override; - virtual bool - ShouldStop (Event *event_ptr); + bool + ShouldStop(Event *event_ptr) override; - virtual bool - MischiefManaged (); + bool + MischiefManaged() override; - virtual bool - WillStop (); + bool + WillStop() override; - virtual bool - StopOthers (); + bool + StopOthers() override; - virtual void - DidPush (); + void + DidPush() override; protected: - virtual bool - DoPlanExplainsStop (Event *event_ptr); + bool + DoPlanExplainsStop(Event *event_ptr) override; - virtual lldb::StateType - GetPlanRunState (); + lldb::StateType + GetPlanRunState() override; private: - std::string m_class_name; - StructuredData::ObjectSP m_implementation_sp; + std::string m_class_name; + StructuredData::ObjectSP m_implementation_sp; DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython); }; - } // namespace lldb_private -#endif // liblldb_ThreadPlan_Python_h_ +#endif // liblldb_ThreadPlan_Python_h_ diff --git a/include/lldb/Target/ThreadPlanRunToAddress.h b/include/lldb/Target/ThreadPlanRunToAddress.h index d94820668017..a1b974605ffb 100644 --- a/include/lldb/Target/ThreadPlanRunToAddress.h +++ b/include/lldb/Target/ThreadPlanRunToAddress.h @@ -36,37 +36,35 @@ public: const std::vector &addresses, bool stop_others); + ~ThreadPlanRunToAddress() override; - virtual - ~ThreadPlanRunToAddress (); + void + GetDescription(Stream *s, lldb::DescriptionLevel level) override; - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level); + bool + ValidatePlan(Stream *error) override; - virtual bool - ValidatePlan (Stream *error); + bool + ShouldStop(Event *event_ptr) override; - virtual bool - ShouldStop (Event *event_ptr); - - virtual bool - StopOthers (); + bool + StopOthers() override; - virtual void - SetStopOthers (bool new_value); + void + SetStopOthers(bool new_value) override; - virtual lldb::StateType - GetPlanRunState (); + lldb::StateType + GetPlanRunState() override; - virtual bool - WillStop (); + bool + WillStop() override; - virtual bool - MischiefManaged (); + bool + MischiefManaged() override; protected: - virtual bool - DoPlanExplainsStop (Event *event_ptr); + bool + DoPlanExplainsStop(Event *event_ptr) override; void SetInitialBreakpoints(); bool AtOurAddress(); @@ -77,9 +75,8 @@ private: std::vector m_break_ids; // This is the breakpoint we are using to stop us at m_address. DISALLOW_COPY_AND_ASSIGN (ThreadPlanRunToAddress); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanRunToAddress_h_ +#endif // liblldb_ThreadPlanRunToAddress_h_ diff --git a/include/lldb/Target/ThreadPlanShouldStopHere.h b/include/lldb/Target/ThreadPlanShouldStopHere.h index 26e4a1ec4fe7..a52d9e42effd 100644 --- a/include/lldb/Target/ThreadPlanShouldStopHere.h +++ b/include/lldb/Target/ThreadPlanShouldStopHere.h @@ -74,9 +74,9 @@ public: //------------------------------------------------------------------ ThreadPlanShouldStopHere (ThreadPlan *owner); - ThreadPlanShouldStopHere (ThreadPlan *owner, - const ThreadPlanShouldStopHereCallbacks *callbacks, - void *baton = NULL); + ThreadPlanShouldStopHere(ThreadPlan *owner, + const ThreadPlanShouldStopHereCallbacks *callbacks, + void *baton = nullptr); virtual ~ThreadPlanShouldStopHere(); @@ -139,23 +139,15 @@ protected: // Implement this, and call it in the plan's constructor to set the default flags. virtual void SetFlagsToDefault () = 0; - //------------------------------------------------------------------ - // Classes that inherit from ThreadPlanShouldStopHere can see and modify these - //------------------------------------------------------------------ ThreadPlanShouldStopHereCallbacks m_callbacks; void * m_baton; ThreadPlan *m_owner; lldb_private::Flags m_flags; private: - //------------------------------------------------------------------ - // For ThreadPlanShouldStopHere only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (ThreadPlanShouldStopHere); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanShouldStopHere_h_ +#endif // liblldb_ThreadPlanShouldStopHere_h_ diff --git a/include/lldb/Target/ThreadPlanStepInRange.h b/include/lldb/Target/ThreadPlanStepInRange.h index 3a22e97e30d0..b31d35508271 100644 --- a/include/lldb/Target/ThreadPlanStepInRange.h +++ b/include/lldb/Target/ThreadPlanStepInRange.h @@ -42,14 +42,13 @@ public: LazyBool step_in_avoids_code_without_debug_info, LazyBool step_out_avoids_code_without_debug_info); - virtual - ~ThreadPlanStepInRange (); + ~ThreadPlanStepInRange() override; - virtual void - GetDescription (Stream *s, lldb::DescriptionLevel level); + void + GetDescription(Stream *s, lldb::DescriptionLevel level) override; - virtual bool - ShouldStop (Event *event_ptr); + bool + ShouldStop(Event *event_ptr) override; void SetAvoidRegexp(const char *name); @@ -62,19 +61,19 @@ public: SetDefaultFlagValue (uint32_t new_value); bool - IsVirtualStep(); + IsVirtualStep() override; protected: static bool DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation, void *baton); - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; - virtual bool - DoPlanExplainsStop (Event *event_ptr); + bool + DoPlanExplainsStop(Event *event_ptr) override; - virtual void - SetFlagsToDefault () + void + SetFlagsToDefault() override { GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); } @@ -119,9 +118,8 @@ private: bool m_virtual_step; // true if we've just done a "virtual step", i.e. just moved the inline stack depth. ConstString m_step_into_target; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepInRange_h_ +#endif // liblldb_ThreadPlanStepInRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepInstruction.h b/include/lldb/Target/ThreadPlanStepInstruction.h index 86069ffd9eb5..da83ecadcae6 100644 --- a/include/lldb/Target/ThreadPlanStepInstruction.h +++ b/include/lldb/Target/ThreadPlanStepInstruction.h @@ -23,19 +23,19 @@ namespace lldb_private { class ThreadPlanStepInstruction : public ThreadPlan { public: - virtual ~ThreadPlanStepInstruction (); + ~ThreadPlanStepInstruction() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); - virtual bool IsPlanStale (); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; + bool IsPlanStale() override; protected: - virtual bool DoPlanExplainsStop (Event *event_ptr); + bool DoPlanExplainsStop(Event *event_ptr) override; ThreadPlanStepInstruction (Thread &thread, bool step_over, @@ -57,10 +57,8 @@ private: StackID m_parent_frame_id; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInstruction); - }; - } // namespace lldb_private -#endif // liblldb_ThreadPlanStepInstruction_h_ +#endif // liblldb_ThreadPlanStepInstruction_h_ diff --git a/include/lldb/Target/ThreadPlanStepOut.h b/include/lldb/Target/ThreadPlanStepOut.h index 8c140dc9d95d..ac5696357e9b 100644 --- a/include/lldb/Target/ThreadPlanStepOut.h +++ b/include/lldb/Target/ThreadPlanStepOut.h @@ -33,32 +33,32 @@ public: uint32_t frame_idx, LazyBool step_out_avoids_code_without_debug_info); - virtual ~ThreadPlanStepOut (); + ~ThreadPlanStepOut() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); - virtual void DidPush(); - virtual bool IsPlanStale(); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; + void DidPush() override; + bool IsPlanStale() override; - virtual lldb::ValueObjectSP GetReturnValueObject() + lldb::ValueObjectSP GetReturnValueObject() override { return m_return_valobj_sp; } protected: - virtual void - SetFlagsToDefault () + void + SetFlagsToDefault() override { GetFlags().Set(ThreadPlanStepOut::s_default_flag_values); } - virtual bool DoPlanExplainsStop (Event *event_ptr); - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool DoPlanExplainsStop (Event *event_ptr) override; + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; bool QueueInlinedStepPlan (bool queue_now); private: @@ -95,9 +95,8 @@ private: CalculateReturnValue(); DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepOut_h_ +#endif // liblldb_ThreadPlanStepOut_h_ diff --git a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h index a4806056afb9..944f0e0455ee 100644 --- a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h +++ b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -22,29 +22,31 @@ namespace lldb_private { class ThreadPlanStepOverBreakpoint : public ThreadPlan { public: - virtual ~ThreadPlanStepOverBreakpoint (); - ThreadPlanStepOverBreakpoint (Thread &thread); - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); - virtual void ThreadDestroyed (); - void SetAutoContinue (bool do_it); - virtual bool ShouldAutoContinue(Event *event_ptr); - virtual bool IsPlanStale(); + + ~ThreadPlanStepOverBreakpoint() override; + + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; + void ThreadDestroyed() override; + void SetAutoContinue(bool do_it); + bool ShouldAutoContinue(Event *event_ptr) override; + bool IsPlanStale() override; lldb::addr_t GetBreakpointLoadAddress() const { return m_breakpoint_addr; } + protected: - virtual bool DoPlanExplainsStop (Event *event_ptr); - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool DoPlanExplainsStop(Event *event_ptr) override; + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; void ReenableBreakpointSite (); private: @@ -55,9 +57,8 @@ private: bool m_reenabled_breakpoint_site; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepOverBreakpoint_h_ +#endif // liblldb_ThreadPlanStepOverBreakpoint_h_ diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h index d47c6c9429d5..7defaef7d07d 100644 --- a/include/lldb/Target/ThreadPlanStepOverRange.h +++ b/include/lldb/Target/ThreadPlanStepOverRange.h @@ -25,32 +25,28 @@ class ThreadPlanStepOverRange : public ThreadPlanStepRange, ThreadPlanShouldStopHere { public: - ThreadPlanStepOverRange (Thread &thread, const AddressRange &range, const SymbolContext &addr_context, lldb::RunMode stop_others, LazyBool step_out_avoids_no_debug); - virtual ~ThreadPlanStepOverRange (); + ~ThreadPlanStepOverRange() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ShouldStop (Event *event_ptr); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ShouldStop(Event *event_ptr) override; protected: - virtual bool DoPlanExplainsStop (Event *event_ptr); - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool DoPlanExplainsStop(Event *event_ptr) override; + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; - virtual void - SetFlagsToDefault () + void + SetFlagsToDefault() override { GetFlags().Set(ThreadPlanStepOverRange::s_default_flag_values); } - - - -private: +private: static uint32_t s_default_flag_values; void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info); @@ -59,9 +55,8 @@ private: bool m_first_resume; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepOverRange_h_ +#endif // liblldb_ThreadPlanStepOverRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h index 43c55c2aa411..8f6685f82aab 100644 --- a/include/lldb/Target/ThreadPlanStepRange.h +++ b/include/lldb/Target/ThreadPlanStepRange.h @@ -33,24 +33,22 @@ public: lldb::RunMode stop_others, bool given_ranges_only = false); - virtual ~ThreadPlanStepRange (); - - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level) = 0; - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr) = 0; - virtual Vote ShouldReportStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); - virtual void DidPush (); - virtual bool IsPlanStale (); + ~ThreadPlanStepRange() override; + void GetDescription(Stream *s, lldb::DescriptionLevel level) override = 0; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override = 0; + Vote ShouldReportStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; + void DidPush() override; + bool IsPlanStale() override; void AddRange(const AddressRange &new_range); protected: - bool InRange(); lldb::FrameComparison CompareCurrentFrameToStartFrame(); bool InSymbol(); @@ -88,10 +86,10 @@ protected: private: std::vector m_instruction_ranges; - DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange); + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange); }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepRange_h_ +#endif // liblldb_ThreadPlanStepRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepThrough.h b/include/lldb/Target/ThreadPlanStepThrough.h index 16979663eb1b..43af37c84a06 100644 --- a/include/lldb/Target/ThreadPlanStepThrough.h +++ b/include/lldb/Target/ThreadPlanStepThrough.h @@ -22,20 +22,20 @@ namespace lldb_private { class ThreadPlanStepThrough : public ThreadPlan { public: - virtual ~ThreadPlanStepThrough (); + ~ThreadPlanStepThrough() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); - virtual void DidPush(); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; + void DidPush() override; protected: - virtual bool DoPlanExplainsStop (Event *event_ptr); - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool DoPlanExplainsStop(Event *event_ptr) override; + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; ThreadPlanStepThrough (Thread &thread, StackID &return_stack_id, @@ -49,6 +49,7 @@ protected: private: friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_other_plans, bool stop_others); @@ -63,9 +64,8 @@ private: bool m_stop_others; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepThrough); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepThrough_h_ +#endif // liblldb_ThreadPlanStepThrough_h_ diff --git a/include/lldb/Target/ThreadPlanStepUntil.h b/include/lldb/Target/ThreadPlanStepUntil.h index 5aa3876df53c..3c1bd8c6665d 100644 --- a/include/lldb/Target/ThreadPlanStepUntil.h +++ b/include/lldb/Target/ThreadPlanStepUntil.h @@ -19,33 +19,32 @@ namespace lldb_private { - class ThreadPlanStepUntil : public ThreadPlan { public: - virtual ~ThreadPlanStepUntil (); + ~ThreadPlanStepUntil() override; - virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); - virtual bool ValidatePlan (Stream *error); - virtual bool ShouldStop (Event *event_ptr); - virtual bool StopOthers (); - virtual lldb::StateType GetPlanRunState (); - virtual bool WillStop (); - virtual bool MischiefManaged (); + void GetDescription(Stream *s, lldb::DescriptionLevel level) override; + bool ValidatePlan(Stream *error) override; + bool ShouldStop(Event *event_ptr) override; + bool StopOthers() override; + lldb::StateType GetPlanRunState() override; + bool WillStop() override; + bool MischiefManaged() override; protected: - virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); - virtual bool DoPlanExplainsStop (Event *event_ptr); + bool DoWillResume(lldb::StateType resume_state, bool current_plan) override; + bool DoPlanExplainsStop(Event *event_ptr) override; ThreadPlanStepUntil (Thread &thread, lldb::addr_t *address_list, size_t num_addresses, bool stop_others, uint32_t frame_idx = 0); - void AnalyzeStop(void); -private: + void AnalyzeStop(); +private: StackID m_stack_id; lldb::addr_t m_step_from_insn; lldb::break_id_t m_return_bp_id; @@ -72,9 +71,8 @@ private: // from step in. DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepUntil); - }; } // namespace lldb_private -#endif // liblldb_ThreadPlanStepUntil_h_ +#endif // liblldb_ThreadPlanStepUntil_h_ diff --git a/include/lldb/Target/ThreadPlanTracer.h b/include/lldb/Target/ThreadPlanTracer.h index 4eb0c783e57d..6d064133fa91 100644 --- a/include/lldb/Target/ThreadPlanTracer.h +++ b/include/lldb/Target/ThreadPlanTracer.h @@ -26,7 +26,6 @@ class ThreadPlanTracer friend class ThreadPlan; public: - typedef enum ThreadPlanTracerStyle { eLocation = 0, @@ -34,21 +33,18 @@ public: eCheckFrames, ePython } ThreadPlanTracerStyle; + ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp); ThreadPlanTracer (Thread &thread); - virtual ~ThreadPlanTracer() - { - } + virtual ~ThreadPlanTracer() = default; virtual void TracingStarted () { - } virtual void TracingEnded () { - } bool @@ -90,8 +86,6 @@ protected: Stream * GetLogStream (); - - virtual void Log(); private: @@ -108,12 +102,13 @@ class ThreadPlanAssemblyTracer : public ThreadPlanTracer public: ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp); ThreadPlanAssemblyTracer (Thread &thread); - virtual ~ThreadPlanAssemblyTracer (); - virtual void TracingStarted (); - virtual void TracingEnded (); - virtual void Log(); + ~ThreadPlanAssemblyTracer() override; + + void TracingStarted() override; + void TracingEnded() override; + void Log() override; + private: - Disassembler * GetDisassembler (); @@ -128,4 +123,4 @@ private: } // namespace lldb_private -#endif // liblldb_ThreadPlanTracer_h_ +#endif // liblldb_ThreadPlanTracer_h_ diff --git a/include/lldb/Target/ThreadSpec.h b/include/lldb/Target/ThreadSpec.h index e0d30934f373..95f509a5cb9d 100644 --- a/include/lldb/Target/ThreadSpec.h +++ b/include/lldb/Target/ThreadSpec.h @@ -1,4 +1,4 @@ -//===-- ThreadSpec.h ------------------------------------------------*- C++ -*-===// +//===-- ThreadSpec.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,9 +10,12 @@ #ifndef liblldb_ThreadSpec_h_ #define liblldb_ThreadSpec_h_ -#include +// C Includes +// C++ Includes #include +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" namespace lldb_private { @@ -110,7 +113,7 @@ public: { if (m_name.empty()) return true; - else if (name == NULL) + else if (name == nullptr) return false; else return m_name == name; @@ -124,7 +127,7 @@ public: { if (m_queue_name.empty()) return true; - else if (queue_name == NULL) + else if (queue_name == nullptr) return false; else return m_queue_name == queue_name; @@ -142,7 +145,6 @@ public: void GetDescription (Stream *s, lldb::DescriptionLevel level) const; -protected: private: uint32_t m_index; lldb::tid_t m_tid; @@ -152,4 +154,4 @@ private: } // namespace lldb_private -#endif // liblldb_ThreadSpec_h_ +#endif // liblldb_ThreadSpec_h_ diff --git a/include/lldb/Target/UnixSignals.h b/include/lldb/Target/UnixSignals.h index 76955deabc78..7a02f557067b 100644 --- a/include/lldb/Target/UnixSignals.h +++ b/include/lldb/Target/UnixSignals.h @@ -98,6 +98,9 @@ public: int32_t GetSignalAtIndex(int32_t index) const; + ConstString + GetShortName(ConstString name) const; + // We assume that the elements of this object are constant once it is constructed, // since a process should never need to add or remove symbols as it runs. So don't // call these functions anywhere but the constructor of your subclass of UnixSignals or in @@ -106,11 +109,11 @@ public: void AddSignal (int signo, const char *name, - const char *short_name, bool default_suppress, bool default_stop, bool default_notify, - const char *description); + const char *description, + const char *alias = nullptr); void RemoveSignal (int signo); @@ -123,18 +126,18 @@ protected: struct Signal { ConstString m_name; - ConstString m_short_name; + ConstString m_alias; std::string m_description; bool m_suppress:1, m_stop:1, m_notify:1; Signal (const char *name, - const char *short_name, bool default_suppress, bool default_stop, bool default_notify, - const char *description); + const char *description, + const char *alias); ~Signal () {} }; diff --git a/include/lldb/Target/UnwindAssembly.h b/include/lldb/Target/UnwindAssembly.h index 963949cf07d5..6f53e7e710f5 100644 --- a/include/lldb/Target/UnwindAssembly.h +++ b/include/lldb/Target/UnwindAssembly.h @@ -24,8 +24,7 @@ public: static lldb::UnwindAssemblySP FindPlugin (const ArchSpec &arch); - virtual - ~UnwindAssembly(); + ~UnwindAssembly() override; virtual bool GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, @@ -59,6 +58,4 @@ private: } // namespace lldb_private -#endif //utility_UnwindAssembly_h_ - - +#endif // utility_UnwindAssembly_h_ diff --git a/include/lldb/Utility/AnsiTerminal.h b/include/lldb/Utility/AnsiTerminal.h index 9a5117ae74ea..a43dd1ba4325 100644 --- a/include/lldb/Utility/AnsiTerminal.h +++ b/include/lldb/Utility/AnsiTerminal.h @@ -41,8 +41,13 @@ #define ANSI_CTRL_CONCEAL 8 #define ANSI_CTRL_CROSSED_OUT 9 -#define ANSI_ESC_START "\033[" -#define ANSI_ESC_END "m" +#define ANSI_ESC_START "\033[" +#define ANSI_ESC_END "m" + +#define ANSI_STR(s) #s +#define ANSI_DEF_STR(s) ANSI_STR(s) + +#define ANSI_ESCAPE1(s) ANSI_ESC_START ANSI_DEF_STR(s) ANSI_ESC_END #define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END #define ANSI_2_CTRL(ctrl1,ctrl2) "\033["##ctrl1";"##ctrl2 ANSI_ESC_END diff --git a/include/lldb/Utility/Either.h b/include/lldb/Utility/Either.h new file mode 100644 index 000000000000..ae647363512d --- /dev/null +++ b/include/lldb/Utility/Either.h @@ -0,0 +1,154 @@ +//===-- 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 + +namespace lldb_utility { + template + 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& rhs) + { + switch (rhs.m_selected) + { + case Selected::One: + m_t1 = rhs.GetAs().getValue(); + m_selected = Selected::One; + break; + case Selected::Two: + m_t2 = rhs.GetAs().getValue(); + m_selected = Selected::Two; + break; + } + } + + template ::value>::type * = nullptr> + llvm::Optional + GetAs() const + { + switch (m_selected) + { + case Selected::One: + return m_t1; + default: + return llvm::Optional(); + } + } + + template ::value>::type * = nullptr> + llvm::Optional + GetAs() const + { + switch (m_selected) + { + case Selected::Two: + return m_t2; + default: + return llvm::Optional(); + } + } + + template + ResultType + Apply (std::function if_T1, + std::function 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& rhs) + { + return (GetAs() == rhs.GetAs()) && (GetAs() == rhs.GetAs()); + } + + explicit + operator bool () + { + switch (m_selected) + { + case Selected::One: + return (bool)m_t1; + case Selected::Two: + return (bool)m_t2; + } + } + + Either& + operator = (const Either& rhs) + { + switch (rhs.m_selected) + { + case Selected::One: + m_t1 = rhs.GetAs().getValue(); + m_selected = Selected::One; + break; + case Selected::Two: + m_t2 = rhs.GetAs().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/Utility/Iterable.h b/include/lldb/Utility/Iterable.h index 17c8cf4d2319..2317225d126f 100644 --- a/include/lldb/Utility/Iterable.h +++ b/include/lldb/Utility/Iterable.h @@ -10,6 +10,12 @@ #ifndef liblldb_Iterable_h_ #define liblldb_Iterable_h_ +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes #include "lldb/Host/Mutex.h" namespace lldb_private @@ -34,9 +40,7 @@ template class Ad { public: typedef typename C::const_iterator BackingIterator; -private: - BackingIterator m_iter; -public: + // Wrapping constructor AdaptedConstIterator (BackingIterator backing_iterator) : m_iter(backing_iterator) @@ -63,7 +67,7 @@ public: } // Destructible - ~AdaptedConstIterator () { } + ~AdaptedConstIterator() = default; // Comparable bool operator== (const AdaptedConstIterator &rhs) @@ -160,6 +164,9 @@ public: template friend void swap(AdaptedConstIterator &, AdaptedConstIterator &); + +private: + BackingIterator m_iter; }; template @@ -203,8 +210,6 @@ public: template class LockingAdaptedIterable : public AdaptedIterable { -private: - Mutex *m_mutex = nullptr; public: LockingAdaptedIterable (C &container, Mutex &mutex) : AdaptedIterable(container), @@ -217,7 +222,7 @@ public: AdaptedIterable(rhs), m_mutex(rhs.m_mutex) { - rhs.m_mutex = NULL; + rhs.m_mutex = nullptr; } ~LockingAdaptedIterable () @@ -227,9 +232,11 @@ public: } private: + Mutex *m_mutex = nullptr; + DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable); }; -} +} // namespace lldb_private -#endif +#endif // liblldb_Iterable_h_ diff --git a/include/lldb/Utility/JSON.h b/include/lldb/Utility/JSON.h index da5e26dbda28..e61c5ee85017 100644 --- a/include/lldb/Utility/JSON.h +++ b/include/lldb/Utility/JSON.h @@ -71,8 +71,8 @@ namespace lldb_private { JSONString& operator = (const JSONString& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -84,8 +84,7 @@ namespace lldb_private { return V->GetKind() == JSONValue::Kind::String; } - virtual - ~JSONString () = default; + ~JSONString() override = default; private: @@ -98,43 +97,79 @@ namespace lldb_private { class JSONNumber : public JSONValue { public: - JSONNumber (); - explicit JSONNumber (uint64_t i); - explicit JSONNumber (double d); + typedef std::shared_ptr SP; + + // We cretae a constructor for all integer and floating point type with using templates and + // SFINAE to avoid having ambiguous overloads because of the implicit type promotion. If we + // would have constructors only with int64_t, uint64_t and double types then constructing a + // JSONNumber from an int32_t (or any other similar type) would fail to compile. + + template ::value && + std::is_unsigned::value>::type* = nullptr> + explicit JSONNumber (T u) : + JSONValue(JSONValue::Kind::Number), + m_data_type(DataType::Unsigned) + { + m_data.m_unsigned = u; + } + + template ::value && + std::is_signed::value>::type* = nullptr> + explicit JSONNumber (T s) : + JSONValue(JSONValue::Kind::Number), + m_data_type(DataType::Signed) + { + m_data.m_signed = s; + } + + template ::value>::type* = nullptr> + explicit JSONNumber (T d) : + JSONValue(JSONValue::Kind::Number), + m_data_type(DataType::Double) + { + m_data.m_double = d; + } + + ~JSONNumber() override = default; JSONNumber (const JSONNumber& s) = delete; JSONNumber& operator = (const JSONNumber& s) = delete; - virtual void - Write (Stream& s); - - typedef std::shared_ptr SP; + void + Write(Stream& s) override; uint64_t - GetData () { return m_data; } + GetAsUnsigned() const; + + int64_t + GetAsSigned() const; double - GetAsDouble() - { - if (m_is_integer) - return (double)m_data; - else - return m_double; - } + GetAsDouble() const; static bool classof(const JSONValue *V) { return V->GetKind() == JSONValue::Kind::Number; } - - virtual - ~JSONNumber () = default; - + private: - bool m_is_integer; - uint64_t m_data; - double m_double; + enum class DataType : uint8_t + { + Unsigned, + Signed, + Double + } m_data_type; + + union + { + uint64_t m_unsigned; + int64_t m_signed; + double m_double; + } m_data; }; class JSONTrue : public JSONValue @@ -146,8 +181,8 @@ namespace lldb_private { JSONTrue& operator = (const JSONTrue& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -156,8 +191,7 @@ namespace lldb_private { return V->GetKind() == JSONValue::Kind::True; } - virtual - ~JSONTrue () = default; + ~JSONTrue() override = default; }; class JSONFalse : public JSONValue @@ -169,8 +203,8 @@ namespace lldb_private { JSONFalse& operator = (const JSONFalse& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -179,8 +213,7 @@ namespace lldb_private { return V->GetKind() == JSONValue::Kind::False; } - virtual - ~JSONFalse () = default; + ~JSONFalse() override = default; }; class JSONNull : public JSONValue @@ -192,8 +225,8 @@ namespace lldb_private { JSONNull& operator = (const JSONNull& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -202,8 +235,7 @@ namespace lldb_private { return V->GetKind() == JSONValue::Kind::Null; } - virtual - ~JSONNull () = default; + ~JSONNull() override = default; }; class JSONObject : public JSONValue @@ -215,8 +247,8 @@ namespace lldb_private { JSONObject& operator = (const JSONObject& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -232,8 +264,7 @@ namespace lldb_private { JSONValue::SP GetObject (const std::string& key); - virtual - ~JSONObject () = default; + ~JSONObject() override = default; private: typedef std::map Map; @@ -250,8 +281,8 @@ namespace lldb_private { JSONArray& operator = (const JSONArray& s) = delete; - virtual void - Write (Stream& s); + void + Write(Stream& s) override; typedef std::shared_ptr SP; @@ -280,13 +311,11 @@ namespace lldb_private { Size GetNumElements (); - virtual - ~JSONArray () = default; + ~JSONArray() override = default; Vector m_elements; }; - class JSONParser : public StringExtractor { public: @@ -327,6 +356,6 @@ namespace lldb_private { JSONValue::SP ParseJSONArray (); }; -} +} // namespace lldb_private -#endif // utility_ProcessStructReader_h_ +#endif // utility_JSON_h_ diff --git a/include/lldb/Utility/ProcessStructReader.h b/include/lldb/Utility/ProcessStructReader.h index d053b702462e..80f90feb87ab 100644 --- a/include/lldb/Utility/ProcessStructReader.h +++ b/include/lldb/Utility/ProcessStructReader.h @@ -16,7 +16,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" #include @@ -29,7 +29,7 @@ namespace lldb_private { protected: struct FieldImpl { - ClangASTType type; + CompilerType type; size_t offset; size_t size; }; @@ -40,7 +40,7 @@ namespace lldb_private { size_t m_addr_byte_size; public: - ProcessStructReader (Process *process, lldb::addr_t base_addr, ClangASTType struct_type) + ProcessStructReader (Process *process, lldb::addr_t base_addr, CompilerType struct_type) { if (!process) return; @@ -55,7 +55,7 @@ namespace lldb_private { uint64_t bit_offset; uint32_t bitfield_bit_size; bool is_bitfield; - ClangASTType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield); + CompilerType field_type = struct_type.GetFieldAtIndex(idx,name,&bit_offset,&bitfield_bit_size,&is_bitfield); // no support for bitfields in here (yet) if (is_bitfield) return; diff --git a/include/lldb/Utility/PseudoTerminal.h b/include/lldb/Utility/PseudoTerminal.h index 595b2fc19bfd..d73253497746 100644 --- a/include/lldb/Utility/PseudoTerminal.h +++ b/include/lldb/Utility/PseudoTerminal.h @@ -260,7 +260,7 @@ private: }; -} // namespace lldb +} // namespace lldb_utility #endif // #if defined(__cplusplus) #endif // #ifndef liblldb_PseudoTerminal_h_ diff --git a/include/lldb/Utility/PythonPointer.h b/include/lldb/Utility/PythonPointer.h deleted file mode 100644 index fe90670fd2e1..000000000000 --- a/include/lldb/Utility/PythonPointer.h +++ /dev/null @@ -1,73 +0,0 @@ -//===---------------------PythonPointer.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_PythonPointer_h_ -#define utility_PythonPointer_h_ - -#include - -#include "lldb/lldb-python.h" - -namespace lldb_private { - -template -class PythonPointer -{ -public: - typedef PyObject* element_type; -private: - element_type* ptr_; - bool my_ref; -public: - - PythonPointer(element_type p, bool steal_ref = false) : - ptr_(p), - my_ref(!steal_ref) - { - if (my_ref) - Py_INCREF(ptr_); - } - - PythonPointer(const PythonPointer& r, bool steal_ref = false) : - ptr_(r.ptr_), - my_ref(!steal_ref) - { - if (my_ref) - Py_INCREF(ptr_); - } - - ~PythonPointer() - { - if (my_ref) - Py_XDECREF(ptr_); - } - - PythonPointer - StealReference() - { - return PythonPointer(ptr_,true); - } - - PythonPointer - DuplicateReference() - { - return PythonPointer(ptr_, false); - } - - element_type get() const {return ptr_;} - - bool IsNull() { return ptr_ == NULL; } - bool IsNone() { return ptr_ == Py_None; } - - operator PyObject* () { return ptr_; } -}; - -} // namespace lldb - -#endif // utility_PythonPointer_h_ diff --git a/include/lldb/Utility/SharedCluster.h b/include/lldb/Utility/SharedCluster.h index 3a34d8ddb415..2c03c409d97e 100644 --- a/include/lldb/Utility/SharedCluster.h +++ b/include/lldb/Utility/SharedCluster.h @@ -27,14 +27,15 @@ namespace imp shared_ptr_refcount() : shared_count (0) {} - virtual ~shared_ptr_refcount () + ~shared_ptr_refcount() override { } - virtual void on_zero_shared () + void on_zero_shared() override { manager->DecrementRefCount(); } + private: T *manager; }; @@ -100,4 +101,5 @@ private: }; } // namespace lldb_private + #endif // utility_SharedCluster_h_ diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h index 5c77dad9f7ff..29538bc7dc03 100644 --- a/include/lldb/Utility/SharingPtr.h +++ b/include/lldb/Utility/SharingPtr.h @@ -10,6 +10,8 @@ #ifndef utility_SharingPtr_h_ #define utility_SharingPtr_h_ +// C Includes +// C++ Includes #include #include @@ -22,6 +24,9 @@ #include #endif +// 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) @@ -38,6 +43,13 @@ class shared_count shared_count(const shared_count&); shared_count& operator=(const shared_count&); +public: + explicit shared_count(long refs = 0) + : shared_owners_(refs) {} + + void add_shared(); + void release_shared(); + long use_count() const {return shared_owners_ + 1;} protected: #ifdef _MSC_VER long shared_owners_; @@ -45,16 +57,9 @@ protected: std::atomic shared_owners_; #endif virtual ~shared_count(); + private: virtual void on_zero_shared() = 0; - -public: - explicit shared_count(long refs = 0) - : shared_owners_(refs) {} - - void add_shared(); - void release_shared(); - long use_count() const {return shared_owners_ + 1;} }; template @@ -67,7 +72,7 @@ public: : data_(p) {} private: - virtual void on_zero_shared(); + void on_zero_shared() override; // Outlaw copy constructor and assignment operator to keep effective C++ // warnings down to a minimum @@ -113,7 +118,8 @@ public: : data_(a0, a1, a2, a3, a4) {} private: - virtual void on_zero_shared(); + void on_zero_shared() override; + public: T* get() {return &data_;} }; @@ -124,18 +130,20 @@ shared_ptr_emplace::on_zero_shared() { } -} // namespace +} // namespace imp template class SharingPtr { public: typedef T element_type; + private: element_type* ptr_; imp::shared_count* cntrl_; struct nat {int for_bool_;}; + public: SharingPtr(); SharingPtr(std::nullptr_t); @@ -161,7 +169,7 @@ public: element_type* operator->() const {return ptr_;} long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;} bool unique() const {return use_count() == 1;} - bool empty() const {return cntrl_ == 0;} + bool empty() const {return cntrl_ == nullptr;} operator nat*() const {return (nat*)get();} static SharingPtr make_shared(); @@ -182,30 +190,29 @@ public: static SharingPtr make_shared(A0&, A1&, A2&, A3&, A4&); private: - template friend class SharingPtr; }; template inline SharingPtr::SharingPtr() - : ptr_(0), - cntrl_(0) + : ptr_(nullptr), + cntrl_(nullptr) { } template inline SharingPtr::SharingPtr(std::nullptr_t) -: ptr_(0), -cntrl_(0) +: ptr_(nullptr), +cntrl_(nullptr) { } template template SharingPtr::SharingPtr(Y* p) - : ptr_(p), cntrl_(0) + : ptr_(p), cntrl_(nullptr) { std::unique_ptr hold(p); typedef imp::shared_ptr_pointer _CntrlBlk; @@ -431,7 +438,6 @@ make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) return SharingPtr::make_shared(a0, a1, a2, a3, a4); } - template inline bool @@ -490,12 +496,8 @@ public: // action: false means increment just happened // true means decrement is about to happen -private: - Callback cb_; - void* baton_; + LoggingSharingPtr() : cb_(0), baton_(nullptr) {} -public: - LoggingSharingPtr() : cb_(0), baton_(0) {} LoggingSharingPtr(Callback cb, void* baton) : cb_(cb), baton_(baton) { @@ -505,7 +507,7 @@ public: template LoggingSharingPtr(Y* p) - : base(p), cb_(0), baton_(0) {} + : base(p), cb_(0), baton_(nullptr) {} template LoggingSharingPtr(Y* p, Callback cb, void* baton) @@ -568,9 +570,12 @@ public: cb_ = 0; baton_ = 0; } + +private: + Callback cb_; + void* baton_; }; - - + template class IntrusiveSharingPtr; @@ -637,14 +642,10 @@ public: imp::shared_count(-1) { } - - virtual - ~ReferenceCountedBaseVirtual () - { - } - - virtual void on_zero_shared (); - + + ~ReferenceCountedBaseVirtual() override = default; + + void on_zero_shared() override; }; template @@ -716,7 +717,7 @@ public: // those would be builds for release. But for debug and release builds // that are for development, we NULL out the pointers to catch potential // issues. - ptr_ = NULL; + ptr_ = nullptr; #endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) } @@ -754,7 +755,7 @@ public: } void - reset(T* ptr = NULL) + reset(T* ptr = nullptr) { IntrusiveSharingPtr(ptr).swap(*this); } @@ -793,7 +794,7 @@ private: if (ptr_) { #if defined (ENABLE_SP_LOGGING) - track_sp (this, NULL, ptr_->use_count() - 1); + track_sp (this, nullptr, ptr_->use_count() - 1); #endif ptr_->release_shared(); } @@ -838,4 +839,4 @@ inline bool operator!= (T* lhs, const IntrusiveSharingPtr& rhs) } // namespace lldb_private -#endif // utility_SharingPtr_h_ +#endif // utility_SharingPtr_h_ diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h index 0f2dbb166be1..db1b83b07694 100644 --- a/include/lldb/Utility/StringExtractor.h +++ b/include/lldb/Utility/StringExtractor.h @@ -114,6 +114,9 @@ public: uint8_t GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true); + bool + GetHexU8Ex (uint8_t& ch, bool set_eof_on_fail = true); + bool GetNameColonValue (std::string &name, std::string &value); diff --git a/include/lldb/Utility/TaskPool.h b/include/lldb/Utility/TaskPool.h new file mode 100644 index 000000000000..443e2a5853e2 --- /dev/null +++ b/include/lldb/Utility/TaskPool.h @@ -0,0 +1,221 @@ +//===--------------------- TaskPool.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_TaskPool_h_ +#define utility_TaskPool_h_ + +#if defined(__cplusplus) && defined(_MSC_VER) && (_HAS_EXCEPTIONS == 0) +// Compiling MSVC libraries with _HAS_EXCEPTIONS=0, eliminates most but not all +// calls to __uncaught_exception. Unfortunately, it does seem to eliminate +// the delcaration of __uncaught_excpeiton. Including ensures that it is +// declared. This may not be necessary after MSVC 12. +#include +#endif + +#if defined(_MSC_VER) +// Due to another bug in MSVC 2013, including will generate hundreds of +// warnings in the Concurrency Runtime. This can be removed when we switch to +// MSVC 2015 +#pragma warning(push) +#pragma warning(disable:4062) +#endif + +#include +#include +#include +#include +#include +#include +#include + +// Global TaskPool class for running tasks in parallel on a set of worker thread created the first +// time the task pool is used. The TaskPool provide no gurantee about the order the task will be run +// and about what tasks will run in parrallel. None of the task added to the task pool should block +// on something (mutex, future, condition variable) what will be set only by the completion of an +// other task on the task pool as they may run on the same thread sequentally. +class TaskPool +{ +public: + // Add a new task to the task pool and return a std::future belonging to the newly created task. + // The caller of this function has to wait on the future for this task to complete. + template + static std::future::type> + AddTask(F&& f, Args&&... args); + + // Run all of the specified tasks on the task pool and wait until all of them are finished + // before returning. This method is intended to be used for small number tasks where listing + // them as function arguments is acceptable. For running large number of tasks you should use + // AddTask for each task and then call wait() on each returned future. + template + static void + RunTasks(T&&... tasks); + +private: + TaskPool() = delete; + + template + struct RunTaskImpl; + + static void + AddTaskImpl(std::function&& task_fn); +}; + +// Wrapper class around the global TaskPool implementation to make it possible to create a set of +// tasks and then wait for the tasks to be completed by the WaitForNextCompletedTask call. This +// class should be used when WaitForNextCompletedTask is needed because this class add no other +// extra functionality to the TaskPool class and it have a very minor performance overhead. +template // The return type of the tasks what will be added to this task runner +class TaskRunner +{ +public: + // Add a task to the task runner what will also add the task to the global TaskPool. The + // function doesn't return the std::future for the task because it will be supplied by the + // WaitForNextCompletedTask after the task is completed. + template + void + AddTask(F&& f, Args&&... args); + + // Wait for the next task in this task runner to finish and then return the std::future what + // belongs to the finished task. If there is no task in this task runner (neither pending nor + // comleted) then this function will return an invalid future. Usually this function should be + // called in a loop processing the results of the tasks until it returns an invalid std::future + // what means that all task in this task runner is completed. + std::future + WaitForNextCompletedTask(); + + // Convenience method to wait for all task in this TaskRunner to finish. Do NOT use this class + // just because of this method. Use TaskPool instead and wait for each std::future returned by + // AddTask in a loop. + void + WaitForAllTasks(); + +private: + std::list> m_ready; + std::list> m_pending; + std::mutex m_mutex; + std::condition_variable m_cv; +}; + +template +std::future::type> +TaskPool::AddTask(F&& f, Args&&... args) +{ + auto task_sp = std::make_shared::type()>>( + std::bind(std::forward(f), std::forward(args)...)); + + AddTaskImpl([task_sp]() { (*task_sp)(); }); + + return task_sp->get_future(); +} + +template +void +TaskPool::RunTasks(T&&... tasks) +{ + RunTaskImpl::Run(std::forward(tasks)...); +} + +template +struct TaskPool::RunTaskImpl +{ + static void + Run(Head&& h, Tail&&... t) + { + auto f = AddTask(std::forward(h)); + RunTaskImpl::Run(std::forward(t)...); + f.wait(); + } +}; + +template<> +struct TaskPool::RunTaskImpl<> +{ + static void + Run() {} +}; + +template +template +void +TaskRunner::AddTask(F&& f, Args&&... args) +{ + std::unique_lock lock(m_mutex); + auto it = m_pending.emplace(m_pending.end()); + *it = std::move(TaskPool::AddTask( + [this, it](F f, Args... args) + { + T&& r = f(std::forward(args)...); + + std::unique_lock lock(this->m_mutex); + this->m_ready.splice(this->m_ready.end(), this->m_pending, it); + lock.unlock(); + + this->m_cv.notify_one(); + return r; + }, + std::forward(f), + std::forward(args)...)); +} + +template <> +template +void +TaskRunner::AddTask(F&& f, Args&&... args) +{ + std::unique_lock lock(m_mutex); + auto it = m_pending.emplace(m_pending.end()); + *it = std::move(TaskPool::AddTask( + [this, it](F f, Args... args) + { + f(std::forward(args)...); + + std::unique_lock lock(this->m_mutex); + this->m_ready.emplace_back(std::move(*it)); + this->m_pending.erase(it); + lock.unlock(); + + this->m_cv.notify_one(); + }, + std::forward(f), + std::forward(args)...)); +} + +template +std::future +TaskRunner::WaitForNextCompletedTask() +{ + std::unique_lock lock(m_mutex); + if (m_ready.empty() && m_pending.empty()) + return std::future(); // No more tasks + + if (m_ready.empty()) + m_cv.wait(lock, [this](){ return !this->m_ready.empty(); }); + + std::future res = std::move(m_ready.front()); + m_ready.pop_front(); + + lock.unlock(); + res.wait(); + + return std::move(res); +} + +template +void +TaskRunner::WaitForAllTasks() +{ + while (WaitForNextCompletedTask().valid()); +} + + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif // #ifndef utility_TaskPool_h_ diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h index 9dce69aef32b..175cecd7e322 100644 --- a/include/lldb/lldb-defines.h +++ b/include/lldb/lldb-defines.h @@ -137,6 +137,8 @@ #define __attribute__(X) #endif +#define UNUSED_IF_ASSERT_DISABLED(x) ((void)(x)) + #if defined(__cplusplus) //---------------------------------------------------------------------- diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index 28614ffb23e1..ea31752b09be 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -146,6 +146,7 @@ namespace lldb { eFormatVectorOfUInt32, eFormatVectorOfSInt64, eFormatVectorOfUInt64, + eFormatVectorOfFloat16, eFormatVectorOfFloat32, eFormatVectorOfFloat64, eFormatVectorOfUInt128, @@ -188,11 +189,11 @@ namespace lldb { //---------------------------------------------------------------------- enum RegisterKind { - eRegisterKindGCC = 0, // the register numbers seen in eh_frame - eRegisterKindDWARF, // the register numbers seen DWARF - eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target - eRegisterKindGDB, // the register numbers gdb uses (matches stabs numbers) - eRegisterKindLLDB, // lldb's internal register numbers + eRegisterKindEHFrame = 0, // the register numbers seen in eh_frame + eRegisterKindDWARF, // the register numbers seen DWARF + eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target + eRegisterKindProcessPlugin, // num used by the process plugin - e.g. by the remote gdb-protocol stub program + eRegisterKindLLDB, // lldb's internal register numbers kNumRegisterKinds }; @@ -421,7 +422,7 @@ namespace lldb { eLanguageTypeFortran03 = 0x0022, ///< ISO Fortran 2003. eLanguageTypeFortran08 = 0x0023, ///< ISO Fortran 2008. // Vendor Extensions - // Note: LanguageRuntime::GetNameForLanguageType + // Note: Language::GetNameForLanguageType // assumes these can be used as indexes into array language_names, and // Language::SetLanguageFromCString and Language::AsCString // assume these can be used as indexes into array g_languages. @@ -595,16 +596,19 @@ namespace lldb { eSectionTypeDataObjCMessageRefs, // Pointer to function pointer + selector eSectionTypeDataObjCCFStrings, // Objective C const CFString/NSString objects eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugAddr, eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, + eSectionTypeDWARFDebugMacro, eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr, + eSectionTypeDWARFDebugStrOffsets, eSectionTypeDWARFAppleNames, eSectionTypeDWARFAppleTypes, eSectionTypeDWARFAppleNamespaces, @@ -614,7 +618,10 @@ namespace lldb { eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section eSectionTypeEHFrame, + eSectionTypeARMexidx, + eSectionTypeARMextab, eSectionTypeCompactUnwind, // compact unwind section in Mach-O, __TEXT,__unwind_info + eSectionTypeGoSymtab, eSectionTypeOther }; @@ -729,15 +736,16 @@ namespace lldb { //---------------------------------------------------------------------- FLAGS_ENUM(TypeOptions) { - eTypeOptionNone = (0u), - eTypeOptionCascade = (1u << 0), - eTypeOptionSkipPointers = (1u << 1), - eTypeOptionSkipReferences = (1u << 2), - eTypeOptionHideChildren = (1u << 3), - eTypeOptionHideValue = (1u << 4), - eTypeOptionShowOneLiner = (1u << 5), - eTypeOptionHideNames = (1u << 6), - eTypeOptionNonCacheable = (1u << 7) + eTypeOptionNone = (0u), + eTypeOptionCascade = (1u << 0), + eTypeOptionSkipPointers = (1u << 1), + eTypeOptionSkipReferences = (1u << 2), + eTypeOptionHideChildren = (1u << 3), + eTypeOptionHideValue = (1u << 4), + eTypeOptionShowOneLiner = (1u << 5), + eTypeOptionHideNames = (1u << 6), + eTypeOptionNonCacheable = (1u << 7), + eTypeOptionHideEmptyAggregates = (1u << 8) }; //---------------------------------------------------------------------- @@ -953,7 +961,8 @@ namespace lldb { eTypeIsInteger = (1u << 18), eTypeIsFloat = (1u << 19), eTypeIsComplex = (1u << 20), - eTypeIsSigned = (1u << 21) + eTypeIsSigned = (1u << 21), + eTypeInstanceIsPointer = (1u << 22) }; FLAGS_ENUM(CommandFlags) diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h index da90ac4775ee..516f31911c2b 100644 --- a/include/lldb/lldb-forward.h +++ b/include/lldb/lldb-forward.h @@ -25,8 +25,10 @@ class AddressImpl; class AddressRange; class AddressResolver; class ArchSpec; +class ArmUnwindInfo; class Args; class ASTResultSynthesizer; +class ASTStructExtractor; class Baton; class Block; class Breakpoint; @@ -48,26 +50,22 @@ class ClangASTContext; class ClangASTImporter; class ClangASTMetadata; class ClangASTSource; -class ClangASTType; -class ClangNamespaceDecl; -class ClangExpression; class ClangExpressionDeclMap; class ClangExpressionParser; class ClangExpressionVariable; -class ClangExpressionVariableList; -class ClangExpressionVariableList; class ClangExpressionVariables; -class ClangFunction; class ClangModulesDeclVendor; class ClangPersistentVariables; -class ClangUserExpression; -class ClangUtilityFunction; class CommandInterpreter; class CommandInterpreterRunOptions; class CommandObject; class CommandReturnObject; class Communication; class CompactUnwindInfo; +struct CompilerContext; +class CompilerDecl; +class CompilerDeclContext; +class CompilerType; class CompileUnit; class Condition; class Connection; @@ -82,7 +80,7 @@ class DataExtractor; class Debugger; class Declaration; class Disassembler; -struct DumpValueObjectOptions; +class DumpValueObjectOptions; class DynamicCheckerFunctions; class DynamicLoader; class Editline; @@ -95,10 +93,15 @@ class ExecutionContext; class ExecutionContextRef; class ExecutionContextRefLocker; class ExecutionContextScope; +class Expression; +class ExpressionVariable; +class ExpressionVariableList; +class ExpressionTypeSystemHelper; class File; class FileSpec; class FileSpecList; class Flags; +class GoASTContext; class TypeCategoryImpl; class FormatManager; class FormattersMatchCandidate; @@ -114,6 +117,8 @@ class IOObject; class IRExecutionUnit; class JITLoader; class JITLoaderList; +class Language; +class LanguageCategory; class LanguageRuntime; class MemoryRegionInfo; class LineTable; @@ -130,6 +135,7 @@ class ModuleSpecList; class Mutex; struct NameSearchContext; class ObjCLanguageRuntime; +class ObjCRuntimeSyntheticProvider; class ObjectContainer; class OptionGroup; class OptionGroupOptions; @@ -160,6 +166,8 @@ class OptionValueUInt64; class OptionValueUUID; class NamedOption; class PathMappingList; +class FunctionCaller; +class PersistentExpressionState; class Platform; class Process; class ProcessAttachInfo; @@ -177,12 +185,11 @@ class RegisterLocation; class RegisterLocationList; class RegisterValue; class RegularExpression; +class REPL; class Scalar; class ScriptInterpreter; class ScriptInterpreterLocker; -#ifndef LLDB_DISABLE_PYTHON struct ScriptSummaryFormat; -#endif class SearchFilter; class Section; class SectionImpl; @@ -221,6 +228,7 @@ class Symtab; class SyntheticChildren; class SyntheticChildrenFrontEnd; class TypeFilterImpl; +class TypeSystem; #ifndef LLDB_DISABLE_PYTHON class ScriptedSyntheticChildren; #endif @@ -249,6 +257,7 @@ class TypeAndOrName; class TypeCategoryMap; class TypeImpl; class TypeList; +class TypeMap; class TypeListImpl; class TypeMemberImpl; class TypeMemberFunctionImpl; @@ -264,6 +273,8 @@ class Unwind; class UnwindAssembly; class UnwindPlan; class UnwindTable; +class UserExpression; +class UtilityFunction; class VMRange; class Value; class ValueList; @@ -300,12 +311,10 @@ namespace lldb { typedef std::shared_ptr BreakpointResolverSP; typedef std::shared_ptr BroadcasterSP; typedef std::unique_ptr ClangASTContextUP; - typedef std::unique_ptr ClangASTImporterUP; - typedef std::unique_ptr ClangASTSourceUP; - typedef std::shared_ptr ClangExpressionVariableSP; + typedef std::shared_ptr ClangASTImporterSP; typedef std::unique_ptr ClangModulesDeclVendorUP; typedef std::unique_ptr ClangPersistentVariablesUP; - typedef std::shared_ptr ClangUserExpressionSP; + typedef std::shared_ptr UserExpressionSP; typedef std::shared_ptr CommandObjectSP; typedef std::shared_ptr CommunicationSP; typedef std::shared_ptr ConnectionSP; @@ -320,14 +329,18 @@ namespace lldb { typedef std::unique_ptr DynamicLoaderUP; typedef std::shared_ptr EventSP; typedef std::shared_ptr ExecutionContextRefSP; + typedef std::shared_ptr ExpressionVariableSP; typedef std::shared_ptr FileSP; typedef std::shared_ptr FunctionSP; + typedef std::shared_ptr FunctionCallerSP; typedef std::shared_ptr FuncUnwindersSP; + typedef std::unique_ptr GoASTContextUP; typedef std::shared_ptr InlineFunctionInfoSP; typedef std::shared_ptr InstructionSP; typedef std::shared_ptr InstrumentationRuntimeSP; typedef std::shared_ptr IOHandlerSP; typedef std::shared_ptr IOObjectSP; + typedef std::shared_ptr IRExecutionUnitSP; typedef std::shared_ptr JITLoaderSP; typedef std::unique_ptr JITLoaderListUP; typedef std::shared_ptr LanguageRuntimeSP; @@ -373,9 +386,10 @@ namespace lldb { typedef std::shared_ptr QueueSP; typedef std::weak_ptr QueueWP; typedef std::shared_ptr QueueItemSP; -#ifndef LLDB_DISABLE_PYTHON + typedef std::shared_ptr REPLSP; typedef std::shared_ptr ScriptSummaryFormatSP; -#endif // #ifndef LLDB_DISABLE_PYTHON + typedef std::shared_ptr ScriptInterpreterSP; + typedef std::unique_ptr ScriptInterpreterUP; typedef std::shared_ptr SectionSP; typedef std::unique_ptr SectionListUP; typedef std::weak_ptr SectionWP; @@ -415,6 +429,7 @@ namespace lldb { typedef std::shared_ptr TypeMemberFunctionImplSP; typedef std::shared_ptr TypeEnumMemberImplSP; typedef std::shared_ptr TypeFilterImplSP; + typedef std::shared_ptr TypeSystemSP; typedef std::shared_ptr TypeFormatImplSP; typedef std::shared_ptr TypeNameSpecifierImplSP; typedef std::shared_ptr TypeSummaryImplSP; @@ -427,6 +442,7 @@ namespace lldb { typedef std::weak_ptr UnixSignalsWP; typedef std::shared_ptr UnwindAssemblySP; typedef std::shared_ptr UnwindPlanSP; + typedef std::shared_ptr UtilityFunctionSP; typedef lldb_private::SharingPtr ValueObjectSP; typedef std::shared_ptr ValueSP; typedef std::shared_ptr ValueListSP; diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h index c62863d744c7..5f8f96c6da46 100644 --- a/include/lldb/lldb-private-enumerations.h +++ b/include/lldb/lldb-private-enumerations.h @@ -106,13 +106,6 @@ typedef enum SortOrder eSortOrderByName } SortOrder; -typedef enum ObjCRuntimeVersions { - eObjC_VersionUnknown = 0, - eAppleObjC_V1 = 1, - eAppleObjC_V2 = 2 -} ObjCRuntimeVersions; - - //---------------------------------------------------------------------- // LazyBool is for boolean values that need to be calculated lazily. // Values start off set to eLazyBoolCalculate, and then they can be @@ -188,7 +181,7 @@ typedef enum FormatterChoiceCriterion eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002, eFormatterChoiceCriterionRegularExpressionSummary = 0x00000004, eFormatterChoiceCriterionRegularExpressionFilter = 0x00000004, - eFormatterChoiceCriterionDynamicObjCDiscovery = 0x00000008, + eFormatterChoiceCriterionLanguagePlugin = 0x00000008, eFormatterChoiceCriterionStrippedBitField = 0x00000010, eFormatterChoiceCriterionWentToStaticValue = 0x00000020 } FormatterChoiceCriterion; @@ -248,6 +241,25 @@ enum class TypeValidatorResult : bool { Success = true, Failure = false }; + +//---------------------------------------------------------------------- +// Enumerations that can be used to specify scopes types when looking up +// types. +//---------------------------------------------------------------------- +enum class CompilerContextKind +{ + Invalid = 0, + TranslationUnit, + Module, + Namespace, + Class, + Structure, + Union, + Function, + Variable, + Enumeration, + Typedef +}; } // namespace lldb_private diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h index 7b5c1c9d2c05..6bc8dadaebff 100644 --- a/include/lldb/lldb-private-interfaces.h +++ b/include/lldb/lldb-private-interfaces.h @@ -14,6 +14,8 @@ #include "lldb/lldb-private.h" +#include + namespace lldb_private { typedef lldb::ABISP (*ABICreateInstance) (const ArchSpec &arch); @@ -28,11 +30,13 @@ namespace lldb_private typedef LogChannel* (*LogChannelCreateInstance) (); typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type); typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force); + typedef Language *(*LanguageCreateInstance) (lldb::LanguageType language); typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language); typedef lldb::CommandObjectSP (*LanguageRuntimeGetCommandObject) (CommandInterpreter& interpreter); typedef SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process); typedef lldb::PlatformSP (*PlatformCreateInstance) (bool force, const ArchSpec *arch); - typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path); + typedef lldb::ProcessSP (*ProcessCreateInstance) (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path); + typedef lldb::ScriptInterpreterSP (*ScriptInterpreterCreateInstance)(CommandInterpreter &interpreter); typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file); typedef SymbolVendor* (*SymbolVendorCreateInstance) (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); @@ -44,6 +48,10 @@ namespace lldb_private typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance) (const lldb::ProcessSP &process_sp); typedef lldb::InstrumentationRuntimeType (*InstrumentationRuntimeGetType) (); typedef lldb::InstrumentationRuntimeSP (*InstrumentationRuntimeCreateInstance) (const lldb::ProcessSP &process_sp); + typedef lldb::TypeSystemSP (*TypeSystemCreateInstance) (lldb::LanguageType language, Module *module, Target *target); + typedef lldb::REPLSP (*REPLCreateInstance) (Error &error, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options); + typedef void (*TypeSystemEnumerateSupportedLanguages) (std::set &languages_for_types, std::set &languages_for_expressions); + typedef void (*REPLEnumerateSupportedLanguages) (std::set &languages); typedef int (*ComparisonFunction)(const void *, const void *); typedef void (*DebuggerInitializeCallback)(Debugger &debugger); diff --git a/include/lldb/lldb-private-types.h b/include/lldb/lldb-private-types.h index cce637fce279..685034a1fee3 100644 --- a/include/lldb/lldb-private-types.h +++ b/include/lldb/lldb-private-types.h @@ -35,7 +35,7 @@ namespace lldb_private // name (optional), encoding, size in bytes and the default display // format. //---------------------------------------------------------------------- - typedef struct + struct RegisterInfo { const char *name; // Name of this register, can't be NULL const char *alt_name; // Alternate name of this register, can be NULL @@ -51,15 +51,15 @@ namespace lldb_private // for this register will be valid. For example, the value list for ah // would be eax (x86) or rax (x64). uint32_t *invalidate_regs; // List of registers (terminated with LLDB_INVALID_REGNUM). If this value is not - // null, all registers in this list will be invalidateed when the value of this + // null, all registers in this list will be invalidated when the value of this // register changes. For example, the invalidate list for eax would be rax // ax, ah, and al. - } RegisterInfo; + }; //---------------------------------------------------------------------- // Registers are grouped into register sets //---------------------------------------------------------------------- - typedef struct + struct RegisterSet { const char *name; // Name of this register set const char *short_name; // A short name for this register set @@ -69,14 +69,14 @@ namespace lldb_private // register array. For example, if eax is defined at index 4 for a // particular RegisterContext, eax would be included in this RegisterSet // by adding the value 4. Not by adding the value lldb_eax_i386. - } RegisterSet; + }; - typedef struct + struct OptionEnumValueElement { int64_t value; const char *string_value; const char *usage; - } OptionEnumValueElement; + }; struct OptionValidator { @@ -85,7 +85,7 @@ namespace lldb_private virtual const char * ShortConditionString() const = 0; virtual const char * LongConditionString() const = 0; }; - + struct OptionDefinition { uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 @@ -102,6 +102,8 @@ namespace lldb_private // pass it. }; + typedef struct type128 { uint64_t x[2]; } type128; + } // namespace lldb_private #endif // #if defined(__cplusplus) diff --git a/include/lldb/lldb-python.h b/include/lldb/lldb-python.h deleted file mode 100644 index c8ef054f60e1..000000000000 --- a/include/lldb/lldb-python.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- lldb-python.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_lldb_python_h_ -#define LLDB_lldb_python_h_ - -// Python.h needs to be included before any system headers in order to avoid redefinition of macros - -#ifdef LLDB_DISABLE_PYTHON -// Python is disabled in this build -#else - #if defined(__linux__) - // features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined. This value - // may be different from the value that Python defines it to be which results - // in a warning. Undefine _POSIX_C_SOURCE before including Python.h The same - // holds for _XOPEN_SOURCE. - #undef _POSIX_C_SOURCE - #undef _XOPEN_SOURCE - #endif - - // Include python for non windows machines - #include -#endif // LLDB_DISABLE_PYTHON - -#endif // LLDB_lldb_python_h_ diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h index fe902073698d..2cf9904bd9d3 100644 --- a/include/lldb/lldb-types.h +++ b/include/lldb/lldb-types.h @@ -110,7 +110,7 @@ namespace lldb typedef uint64_t offset_t; typedef int32_t break_id_t; typedef int32_t watch_id_t; - typedef void * clang_type_t; + typedef void * opaque_compiler_type_t; typedef uint64_t queue_id_t; } diff --git a/source/API/SBAttachInfo.cpp b/source/API/SBAttachInfo.cpp index 07446df27dff..0f2ab7afc9c2 100644 --- a/source/API/SBAttachInfo.cpp +++ b/source/API/SBAttachInfo.cpp @@ -36,6 +36,15 @@ SBAttachInfo::SBAttachInfo (const char *path, bool wait_for) : 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); + m_opaque_sp->SetWaitForLaunch (wait_for); + m_opaque_sp->SetAsync(async); +} + SBAttachInfo::SBAttachInfo (const SBAttachInfo &rhs) : m_opaque_sp (new ProcessAttachInfo()) { @@ -127,6 +136,13 @@ SBAttachInfo::SetWaitForLaunch (bool b) m_opaque_sp->SetWaitForLaunch (b); } +void +SBAttachInfo::SetWaitForLaunch (bool b, bool async) +{ + m_opaque_sp->SetWaitForLaunch (b); + m_opaque_sp->SetAsync(async); +} + bool SBAttachInfo::GetIgnoreExisting () { diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp index dd4c80caf45d..1f58ddb7152a 100644 --- a/source/API/SBBreakpoint.cpp +++ b/source/API/SBBreakpoint.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// 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" @@ -32,7 +36,6 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" - #include "lldb/lldb-enumerations.h" using namespace lldb; @@ -47,7 +50,6 @@ struct CallbackData class SBBreakpointCallbackBaton : public Baton { public: - SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) : Baton (new CallbackData) { @@ -56,19 +58,18 @@ public: data->callback_baton = baton; } - virtual ~SBBreakpointCallbackBaton() + ~SBBreakpointCallbackBaton() override { CallbackData *data = (CallbackData *)m_data; if (data) { delete data; - m_data = NULL; + m_data = nullptr; } } }; - SBBreakpoint::SBBreakpoint () : m_opaque_sp () { @@ -79,15 +80,12 @@ SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) : { } - SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) : m_opaque_sp (bp_sp) { } -SBBreakpoint::~SBBreakpoint() -{ -} +SBBreakpoint::~SBBreakpoint() = default; const SBBreakpoint & SBBreakpoint::operator = (const SBBreakpoint& rhs) @@ -135,7 +133,6 @@ SBBreakpoint::GetID () const return break_id; } - bool SBBreakpoint::IsValid() const { @@ -169,7 +166,7 @@ SBBreakpoint::FindLocationByAddress (addr_t vm_addr) Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); Address address; Target &target = m_opaque_sp->GetTarget(); - if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) + if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { address.SetRawAddress (vm_addr); } @@ -189,7 +186,7 @@ SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr) Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); Address address; Target &target = m_opaque_sp->GetTarget(); - if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false) + if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { address.SetRawAddress (vm_addr); } @@ -329,7 +326,7 @@ SBBreakpoint::GetCondition () Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); return m_opaque_sp->GetConditionText (); } - return NULL; + return nullptr; } uint32_t @@ -380,7 +377,6 @@ SBBreakpoint::SetThreadID (tid_t tid) if (log) log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")", static_cast(m_opaque_sp.get()), tid); - } tid_t @@ -422,7 +418,7 @@ SBBreakpoint::GetThreadIndex() const { Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); - if (thread_spec != NULL) + if (thread_spec != nullptr) thread_idx = thread_spec->GetIndex(); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -451,12 +447,12 @@ SBBreakpoint::SetThreadName (const char *thread_name) const char * SBBreakpoint::GetThreadName () const { - const char *name = NULL; + const char *name = nullptr; if (m_opaque_sp) { Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate(); - if (thread_spec != NULL) + if (thread_spec != nullptr) name = thread_spec->GetName(); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -484,7 +480,7 @@ SBBreakpoint::SetQueueName (const char *queue_name) const char * SBBreakpoint::GetQueueName () const { - const char *name = NULL; + const char *name = nullptr; if (m_opaque_sp) { Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); @@ -552,13 +548,10 @@ SBBreakpoint::GetDescription (SBStream &s) } bool -SBBreakpoint::PrivateBreakpointHitCallback -( - void *baton, - StoppointCallbackContext *ctx, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id -) +SBBreakpoint::PrivateBreakpointHitCallback(void *baton, + StoppointCallbackContext *ctx, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { ExecutionContext exe_ctx (ctx->exe_ctx_ref); BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id)); @@ -758,8 +751,7 @@ SBBreakpoint::operator *() const bool SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event) { - return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL; - + return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != nullptr; } BreakpointEventType @@ -796,5 +788,3 @@ SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event) num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP())); return num_locations; } - - diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index d901e728105b..21f431dac6a3 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -7,8 +7,12 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-types.h" -#include "lldb/Core/SourceManager.h" + #include "lldb/Core/Listener.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -34,10 +38,7 @@ SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions() m_opaque_up.reset(new CommandInterpreterRunOptions()); } -SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() -{ - -} +SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() = default; bool SBCommandInterpreterRunOptions::GetStopOnContinue () const @@ -126,21 +127,24 @@ SBCommandInterpreterRunOptions::ref () const class CommandPluginInterfaceImplementation : public CommandObjectParsed { public: - CommandPluginInterfaceImplementation (CommandInterpreter &interpreter, - const char *name, - lldb::SBCommandPluginInterface* backend, - const char *help = NULL, - const char *syntax = NULL, - uint32_t flags = 0) : + CommandPluginInterfaceImplementation(CommandInterpreter &interpreter, + const char *name, + lldb::SBCommandPluginInterface* backend, + const char *help = nullptr, + const char *syntax = nullptr, + uint32_t flags = 0) : CommandObjectParsed (interpreter, name, help, syntax, flags), m_backend(backend) {} - virtual bool - IsRemovable() const { return true; } + bool + IsRemovable() const override + { + return true; + } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute(Args& command, CommandReturnObject &result) override { SBCommandReturnObject sb_return(&result); SBCommandInterpreter sb_interpreter(&m_interpreter); @@ -169,6 +173,8 @@ SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) : { } +SBCommandInterpreter::~SBCommandInterpreter() = default; + const SBCommandInterpreter & SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs) { @@ -176,47 +182,34 @@ SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs) return *this; } -SBCommandInterpreter::~SBCommandInterpreter () -{ -} - bool SBCommandInterpreter::IsValid() const { - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } - bool -SBCommandInterpreter::CommandExists (const char *cmd) +SBCommandInterpreter::CommandExists(const char *cmd) { - if (cmd && m_opaque_ptr) - return m_opaque_ptr->CommandExists (cmd); - return false; + return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) : false); } bool SBCommandInterpreter::AliasExists (const char *cmd) { - if (cmd && m_opaque_ptr) - return m_opaque_ptr->AliasExists (cmd); - return false; + return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) : false); } bool -SBCommandInterpreter::IsActive () +SBCommandInterpreter::IsActive() { - if (m_opaque_ptr) - return m_opaque_ptr->IsActive (); - return false; + return (IsValid() ? m_opaque_ptr->IsActive() : false); } const char * SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { - if (m_opaque_ptr) - return m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence (ch).GetCString(); - return NULL; + return (IsValid() ? m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch).GetCString() : nullptr); } lldb::ReturnStatus @@ -247,7 +240,7 @@ SBCommandInterpreter::HandleCommand (const char *command_line, SBExecutionContex result.Clear(); - if (command_line && m_opaque_ptr) + if (command_line && IsValid()) { result.ref().SetInteractive(false); m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr); @@ -290,7 +283,7 @@ SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file, static_cast(result.get())); } - if (!m_opaque_ptr) + if (!IsValid()) { result->AppendError ("SBCommandInterpreter is not valid."); result->SetStatus (eReturnStatusFailed); @@ -315,12 +308,9 @@ SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file, else ctx_ptr = nullptr; - m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(), result.ref()); - } - int SBCommandInterpreter::HandleCompletion (const char *current_line, const char *cursor, @@ -334,7 +324,7 @@ SBCommandInterpreter::HandleCompletion (const char *current_line, // Sanity check the arguments that are passed in: // cursor & last_char have to be within the current_line. - if (current_line == NULL || cursor == NULL || last_char == NULL) + if (current_line == nullptr || cursor == nullptr || last_char == nullptr) return 0; if (cursor < current_line || last_char < current_line) @@ -352,11 +342,11 @@ SBCommandInterpreter::HandleCompletion (const char *current_line, static_cast(last_char - current_line), match_start_point, max_return_elements); - if (m_opaque_ptr) + if (IsValid()) { lldb_private::StringList lldb_matches; - num_completions = m_opaque_ptr->HandleCompletion (current_line, cursor, last_char, match_start_point, - max_return_elements, lldb_matches); + num_completions = m_opaque_ptr->HandleCompletion(current_line, cursor, last_char, match_start_point, + max_return_elements, lldb_matches); SBStringList temp_list (&lldb_matches); matches.AppendList (temp_list); @@ -381,27 +371,21 @@ SBCommandInterpreter::HandleCompletion (const char *current_line, } bool -SBCommandInterpreter::HasCommands () +SBCommandInterpreter::HasCommands() { - if (m_opaque_ptr) - return m_opaque_ptr->HasCommands(); - return false; + return (IsValid() ? m_opaque_ptr->HasCommands() : false); } bool -SBCommandInterpreter::HasAliases () +SBCommandInterpreter::HasAliases() { - if (m_opaque_ptr) - return m_opaque_ptr->HasAliases(); - return false; + return (IsValid() ? m_opaque_ptr->HasAliases() : false); } bool -SBCommandInterpreter::HasAliasOptions () +SBCommandInterpreter::HasAliasOptions() { - if (m_opaque_ptr) - return m_opaque_ptr->HasAliasOptions (); - return false; + return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); } SBProcess @@ -409,7 +393,7 @@ SBCommandInterpreter::GetProcess () { SBProcess sb_process; ProcessSP process_sp; - if (m_opaque_ptr) + if (IsValid()) { TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); if (target_sp) @@ -433,7 +417,7 @@ SBDebugger SBCommandInterpreter::GetDebugger () { SBDebugger sb_debugger; - if (m_opaque_ptr) + if (IsValid()) sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -448,15 +432,13 @@ SBCommandInterpreter::GetDebugger () bool SBCommandInterpreter::GetPromptOnQuit() { - if (m_opaque_ptr) - return m_opaque_ptr->GetPromptOnQuit(); - return false; + return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); } void SBCommandInterpreter::SetPromptOnQuit (bool b) { - if (m_opaque_ptr) + if (IsValid()) m_opaque_ptr->SetPromptOnQuit(b); } @@ -464,7 +446,7 @@ void SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnObject &result) { result.Clear(); - if (command_line && m_opaque_ptr) + if (command_line && IsValid()) { m_opaque_ptr->ResolveCommand(command_line, result.ref()); } @@ -475,7 +457,6 @@ SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnOb } } - CommandInterpreter * SBCommandInterpreter::get () { @@ -499,7 +480,7 @@ void SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &result) { result.Clear(); - if (m_opaque_ptr) + if (IsValid()) { TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); Mutex::Locker api_locker; @@ -524,7 +505,7 @@ void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result) { result.Clear(); - if (m_opaque_ptr) + if (IsValid()) { TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); Mutex::Locker api_locker; @@ -588,7 +569,7 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, lldb::CommandOverrideCallback callback, void *baton) { - if (command_name && command_name[0] && m_opaque_ptr) + if (command_name && command_name[0] && IsValid()) { std::string command_name_str (command_name); CommandObject *cmd_obj = m_opaque_ptr->GetCommandObjectForCommand(command_name_str); @@ -605,7 +586,7 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help) { - CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr,name,help); + CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr, name, help); new_command->SetRemovable (true); lldb::CommandObjectSP new_command_sp(new_command); if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) @@ -617,47 +598,40 @@ lldb::SBCommand SBCommandInterpreter::AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help) { lldb::CommandObjectSP new_command_sp; - new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name,impl,help)); + new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name, impl, help)); if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) return lldb::SBCommand(new_command_sp); return lldb::SBCommand(); } -SBCommand::SBCommand () -{} +SBCommand::SBCommand() = default; SBCommand::SBCommand (lldb::CommandObjectSP cmd_sp) : m_opaque_sp (cmd_sp) {} bool -SBCommand::IsValid () +SBCommand::IsValid() { - return (bool)m_opaque_sp; + return m_opaque_sp.get() != nullptr; } const char* -SBCommand::GetName () +SBCommand::GetName() { - if (IsValid ()) - return m_opaque_sp->GetCommandName (); - return NULL; + return (IsValid() ? m_opaque_sp->GetCommandName() : nullptr); } const char* -SBCommand::GetHelp () +SBCommand::GetHelp() { - if (IsValid ()) - return m_opaque_sp->GetHelp (); - return NULL; + return (IsValid() ? m_opaque_sp->GetHelp() : nullptr); } const char* -SBCommand::GetHelpLong () +SBCommand::GetHelpLong() { - if (IsValid ()) - return m_opaque_sp->GetHelpLong (); - return NULL; + return (IsValid() ? m_opaque_sp->GetHelpLong() : nullptr); } void @@ -679,7 +653,7 @@ SBCommand::AddMultiwordCommand (const char* name, const char* help) { if (!IsValid ()) return lldb::SBCommand(); - if (m_opaque_sp->IsMultiwordObject() == false) + if (!m_opaque_sp->IsMultiwordObject()) return lldb::SBCommand(); CommandObjectMultiword *new_command = new CommandObjectMultiword(m_opaque_sp->GetCommandInterpreter(),name,help); new_command->SetRemovable (true); @@ -694,7 +668,7 @@ SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, c { if (!IsValid ()) return lldb::SBCommand(); - if (m_opaque_sp->IsMultiwordObject() == false) + if (!m_opaque_sp->IsMultiwordObject()) return lldb::SBCommand(); lldb::CommandObjectSP new_command_sp; new_command_sp.reset(new CommandPluginInterfaceImplementation(m_opaque_sp->GetCommandInterpreter(),name,impl,help)); @@ -706,9 +680,7 @@ SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, c uint32_t SBCommand::GetFlags () { - if (!IsValid()) - return 0; - return m_opaque_sp->GetFlags().Get(); + return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); } void diff --git a/source/API/SBCommandReturnObject.cpp b/source/API/SBCommandReturnObject.cpp index 1ae2df76c979..a2ed4d6e8c26 100644 --- a/source/API/SBCommandReturnObject.cpp +++ b/source/API/SBCommandReturnObject.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// 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" @@ -26,7 +30,7 @@ SBCommandReturnObject::SBCommandReturnObject () : SBCommandReturnObject::SBCommandReturnObject (const SBCommandReturnObject &rhs): m_opaque_ap () { - if (rhs.m_opaque_ap.get()) + if (rhs.m_opaque_ap) m_opaque_ap.reset (new CommandReturnObject (*rhs.m_opaque_ap)); } @@ -35,6 +39,8 @@ SBCommandReturnObject::SBCommandReturnObject (CommandReturnObject *ptr) : { } +SBCommandReturnObject::~SBCommandReturnObject() = default; + CommandReturnObject * SBCommandReturnObject::Release () { @@ -46,7 +52,7 @@ SBCommandReturnObject::operator = (const SBCommandReturnObject &rhs) { if (this != &rhs) { - if (rhs.m_opaque_ap.get()) + if (rhs.m_opaque_ap) m_opaque_ap.reset (new CommandReturnObject (*rhs.m_opaque_ap)); else m_opaque_ap.reset(); @@ -54,25 +60,18 @@ SBCommandReturnObject::operator = (const SBCommandReturnObject &rhs) return *this; } - -SBCommandReturnObject::~SBCommandReturnObject () -{ - // m_opaque_ap will automatically delete any pointer it owns -} - bool SBCommandReturnObject::IsValid() const { - return m_opaque_ap.get() != NULL; + return m_opaque_ap.get() != nullptr; } - const char * SBCommandReturnObject::GetOutput () { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - if (m_opaque_ap.get()) + if (m_opaque_ap) { if (log) log->Printf ("SBCommandReturnObject(%p)::GetOutput () => \"%s\"", @@ -83,10 +82,10 @@ SBCommandReturnObject::GetOutput () } if (log) - log->Printf ("SBCommandReturnObject(%p)::GetOutput () => NULL", + log->Printf ("SBCommandReturnObject(%p)::GetOutput () => nullptr", static_cast(m_opaque_ap.get())); - return NULL; + return nullptr; } const char * @@ -94,7 +93,7 @@ SBCommandReturnObject::GetError () { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - if (m_opaque_ap.get()) + if (m_opaque_ap) { if (log) log->Printf ("SBCommandReturnObject(%p)::GetError () => \"%s\"", @@ -105,26 +104,22 @@ SBCommandReturnObject::GetError () } if (log) - log->Printf ("SBCommandReturnObject(%p)::GetError () => NULL", + log->Printf ("SBCommandReturnObject(%p)::GetError () => nullptr", static_cast(m_opaque_ap.get())); - return NULL; + return nullptr; } size_t -SBCommandReturnObject::GetOutputSize () +SBCommandReturnObject::GetOutputSize() { - if (m_opaque_ap.get()) - return strlen (m_opaque_ap->GetOutputData()); - return 0; + return (m_opaque_ap ? strlen(m_opaque_ap->GetOutputData()) : 0); } size_t -SBCommandReturnObject::GetErrorSize () +SBCommandReturnObject::GetErrorSize() { - if (m_opaque_ap.get()) - return strlen(m_opaque_ap->GetErrorData()); - return 0; + return (m_opaque_ap ? strlen(m_opaque_ap->GetErrorData()) : 0); } size_t @@ -154,52 +149,46 @@ SBCommandReturnObject::PutError (FILE *fh) void SBCommandReturnObject::Clear() { - if (m_opaque_ap.get()) + if (m_opaque_ap) m_opaque_ap->Clear(); } lldb::ReturnStatus SBCommandReturnObject::GetStatus() { - if (m_opaque_ap.get()) - return m_opaque_ap->GetStatus(); - return lldb::eReturnStatusInvalid; + return (m_opaque_ap ? m_opaque_ap->GetStatus() : lldb::eReturnStatusInvalid); } void SBCommandReturnObject::SetStatus(lldb::ReturnStatus status) { - if (m_opaque_ap.get()) + if (m_opaque_ap) m_opaque_ap->SetStatus(status); } bool -SBCommandReturnObject::Succeeded () +SBCommandReturnObject::Succeeded() { - if (m_opaque_ap.get()) - return m_opaque_ap->Succeeded(); - return false; + return (m_opaque_ap ? m_opaque_ap->Succeeded() : false); } bool -SBCommandReturnObject::HasResult () +SBCommandReturnObject::HasResult() { - if (m_opaque_ap.get()) - return m_opaque_ap->HasResult(); - return false; + return (m_opaque_ap ? m_opaque_ap->HasResult() : false); } void SBCommandReturnObject::AppendMessage (const char *message) { - if (m_opaque_ap.get()) + if (m_opaque_ap) m_opaque_ap->AppendMessage (message); } void SBCommandReturnObject::AppendWarning (const char *message) { - if (m_opaque_ap.get()) + if (m_opaque_ap) m_opaque_ap->AppendWarning (message); } @@ -222,7 +211,6 @@ SBCommandReturnObject::operator *() const return *(m_opaque_ap.get()); } - CommandReturnObject & SBCommandReturnObject::ref() const { @@ -230,11 +218,10 @@ SBCommandReturnObject::ref() const return *(m_opaque_ap.get()); } - void SBCommandReturnObject::SetLLDBObjectPtr (CommandReturnObject *ptr) { - if (m_opaque_ap.get()) + if (m_opaque_ap) m_opaque_ap.reset (ptr); } @@ -243,7 +230,7 @@ SBCommandReturnObject::GetDescription (SBStream &description) { Stream &strm = description.ref(); - if (m_opaque_ap.get()) + if (m_opaque_ap) { description.Printf ("Status: "); lldb::ReturnStatus status = m_opaque_ap->GetStatus(); @@ -269,25 +256,25 @@ SBCommandReturnObject::GetDescription (SBStream &description) } void -SBCommandReturnObject::SetImmediateOutputFile (FILE *fh) +SBCommandReturnObject::SetImmediateOutputFile(FILE *fh) { - if (m_opaque_ap.get()) - m_opaque_ap->SetImmediateOutputFile (fh); + if (m_opaque_ap) + m_opaque_ap->SetImmediateOutputFile(fh); } void -SBCommandReturnObject::SetImmediateErrorFile (FILE *fh) +SBCommandReturnObject::SetImmediateErrorFile(FILE *fh) { - if (m_opaque_ap.get()) - m_opaque_ap->SetImmediateErrorFile (fh); + if (m_opaque_ap) + m_opaque_ap->SetImmediateErrorFile(fh); } void SBCommandReturnObject::PutCString(const char* string, int len) { - if (m_opaque_ap.get()) + if (m_opaque_ap) { - if (len == 0 || string == NULL || *string == 0) + if (len == 0 || string == nullptr || *string == 0) { return; } @@ -304,27 +291,27 @@ SBCommandReturnObject::PutCString(const char* string, int len) const char * SBCommandReturnObject::GetOutput (bool only_if_no_immediate) { - if (!m_opaque_ap.get()) - return NULL; - if (only_if_no_immediate == false || m_opaque_ap->GetImmediateOutputStream().get() == NULL) + if (!m_opaque_ap) + return nullptr; + if (!only_if_no_immediate || m_opaque_ap->GetImmediateOutputStream().get() == nullptr) return GetOutput(); - return NULL; + return nullptr; } const char * SBCommandReturnObject::GetError (bool only_if_no_immediate) { - if (!m_opaque_ap.get()) - return NULL; - if (only_if_no_immediate == false || m_opaque_ap->GetImmediateErrorStream().get() == NULL) + if (!m_opaque_ap) + return nullptr; + if (!only_if_no_immediate || m_opaque_ap->GetImmediateErrorStream().get() == nullptr) return GetError(); - return NULL; + return nullptr; } size_t SBCommandReturnObject::Printf(const char* format, ...) { - if (m_opaque_ap.get()) + if (m_opaque_ap) { va_list args; va_start (args, format); @@ -338,7 +325,7 @@ SBCommandReturnObject::Printf(const char* format, ...) void SBCommandReturnObject::SetError (lldb::SBError &error, const char *fallback_error_cstr) { - if (m_opaque_ap.get()) + if (m_opaque_ap) { if (error.IsValid()) m_opaque_ap->SetError(error.ref(), fallback_error_cstr); @@ -350,7 +337,6 @@ SBCommandReturnObject::SetError (lldb::SBError &error, const char *fallback_erro void SBCommandReturnObject::SetError (const char *error_cstr) { - if (m_opaque_ap.get() && error_cstr) + if (m_opaque_ap && error_cstr) m_opaque_ap->SetError(error_cstr); } - diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index df2019f5a46b..1645294b5a3f 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/API/SBDebugger.h" #include "lldb/lldb-private.h" @@ -43,13 +47,13 @@ #include "lldb/Target/Process.h" #include "lldb/Target/TargetList.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/DynamicLibrary.h" using namespace lldb; using namespace lldb_private; - static llvm::sys::DynamicLibrary LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error) { @@ -86,13 +90,6 @@ LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& er static llvm::ManagedStatic g_debugger_lifetime; -SBInputReader::SBInputReader() -{ -} -SBInputReader::~SBInputReader() -{ -} - SBError SBInputReader::Initialize(lldb::SBDebugger &sb_debugger, unsigned long (*)(void *, lldb::SBInputReader *, lldb::InputReaderAction, char const *, @@ -106,12 +103,37 @@ void SBInputReader::SetIsDone(bool) { } + bool SBInputReader::IsActive() const { return false; } +SBDebugger::SBDebugger() = default; + +SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) : + m_opaque_sp(debugger_sp) +{ +} + +SBDebugger::SBDebugger(const SBDebugger &rhs) : + m_opaque_sp (rhs.m_opaque_sp) +{ +} + +SBDebugger::~SBDebugger() = default; + +SBDebugger & +SBDebugger::operator = (const SBDebugger &rhs) +{ + if (this != &rhs) + { + m_opaque_sp = rhs.m_opaque_sp; + } + return *this; +} + void SBDebugger::Initialize () { @@ -147,13 +169,13 @@ SBDebugger::Clear () SBDebugger SBDebugger::Create() { - return SBDebugger::Create(false, NULL, NULL); + return SBDebugger::Create(false, nullptr, nullptr); } SBDebugger SBDebugger::Create(bool source_init_files) { - return SBDebugger::Create (source_init_files, NULL, NULL); + return SBDebugger::Create (source_init_files, nullptr, nullptr); } SBDebugger @@ -215,7 +237,7 @@ SBDebugger::Destroy (SBDebugger &debugger) Debugger::Destroy (debugger.m_opaque_sp); - if (debugger.m_opaque_sp.get() != NULL) + if (debugger.m_opaque_sp.get() != nullptr) debugger.m_opaque_sp.reset(); } @@ -237,42 +259,12 @@ SBDebugger::MemoryPressureDetected () ModuleList::RemoveOrphanSharedModules(mandatory); } -SBDebugger::SBDebugger () : - m_opaque_sp () -{ -} - -SBDebugger::SBDebugger(const lldb::DebuggerSP &debugger_sp) : - m_opaque_sp(debugger_sp) -{ -} - -SBDebugger::SBDebugger(const SBDebugger &rhs) : - m_opaque_sp (rhs.m_opaque_sp) -{ -} - -SBDebugger & -SBDebugger::operator = (const SBDebugger &rhs) -{ - if (this != &rhs) - { - m_opaque_sp = rhs.m_opaque_sp; - } - return *this; -} - -SBDebugger::~SBDebugger () -{ -} - bool SBDebugger::IsValid() const { - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } - void SBDebugger::SetAsync (bool b) { @@ -281,12 +273,9 @@ SBDebugger::SetAsync (bool b) } bool -SBDebugger::GetAsync () +SBDebugger::GetAsync() { - if (m_opaque_sp) - return m_opaque_sp->GetAsyncExecution(); - else - return false; + return (m_opaque_sp ? m_opaque_sp->GetAsyncExecution() : false); } void @@ -358,7 +347,7 @@ SBDebugger::GetInputFileHandle () if (stream_file_sp) return stream_file_sp->GetFile().GetStream(); } - return NULL; + return nullptr; } FILE * @@ -370,20 +359,19 @@ SBDebugger::GetOutputFileHandle () if (stream_file_sp) return stream_file_sp->GetFile().GetStream(); } - return NULL; + return nullptr; } FILE * SBDebugger::GetErrorFileHandle () { if (m_opaque_sp) - if (m_opaque_sp) - { - StreamFileSP stream_file_sp (m_opaque_sp->GetErrorFile()); - if (stream_file_sp) - return stream_file_sp->GetFile().GetStream(); - } - return NULL; + { + StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile()); + if (stream_file_sp) + return stream_file_sp->GetFile().GetStream(); + } + return nullptr; } void @@ -432,12 +420,12 @@ SBDebugger::HandleCommand (const char *command) sb_interpreter.HandleCommand (command, result, false); - if (GetErrorFileHandle() != NULL) + if (GetErrorFileHandle() != nullptr) result.PutError (GetErrorFileHandle()); - if (GetOutputFileHandle() != NULL) + if (GetOutputFileHandle() != nullptr) result.PutOutput (GetOutputFileHandle()); - if (m_opaque_sp->GetAsyncExecution() == false) + if (!m_opaque_sp->GetAsyncExecution()) { SBProcess process(GetCommandInterpreter().GetProcess ()); ProcessSP process_sp (process.GetSP()); @@ -492,7 +480,7 @@ SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, { // Drain stdout when we stop just in case we have any bytes while ((len = process.GetSTDOUT (stdio_buffer, sizeof (stdio_buffer))) > 0) - if (out != NULL) + if (out != nullptr) ::fwrite (stdio_buffer, 1, len, out); } @@ -500,7 +488,7 @@ SBDebugger::HandleProcessEvent (const SBProcess &process, const SBEvent &event, { // Drain stderr when we stop just in case we have any bytes while ((len = process.GetSTDERR (stdio_buffer, sizeof (stdio_buffer))) > 0) - if (err != NULL) + if (err != nullptr) ::fwrite (stdio_buffer, 1, len, err); } @@ -524,7 +512,6 @@ SBDebugger::GetSourceManager () return sb_source_manager; } - bool SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len) { @@ -547,7 +534,6 @@ SBDebugger::GetDefaultArchitecture (char *arch_name, size_t arch_name_len) return false; } - bool SBDebugger::SetDefaultArchitecture (const char *arch_name) { @@ -564,12 +550,11 @@ SBDebugger::SetDefaultArchitecture (const char *arch_name) } ScriptLanguage -SBDebugger::GetScriptingLanguage (const char *script_language_name) +SBDebugger::GetScriptingLanguage(const char *script_language_name) { - - return Args::StringToScriptLanguage (script_language_name, - eScriptLanguageDefault, - NULL); + return Args::StringToScriptLanguage(script_language_name, + eScriptLanguageDefault, + nullptr); } const char * @@ -637,7 +622,7 @@ SBDebugger::CreateTarget (const char *filename, } else { - sb_error.SetErrorString("invalid target"); + sb_error.SetErrorString("invalid debugger"); } Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -659,12 +644,12 @@ SBDebugger::CreateTargetWithFileAndTargetTriple (const char *filename, if (m_opaque_sp) { const bool add_dependent_modules = true; - Error error (m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, - filename, - target_triple, - add_dependent_modules, - NULL, - target_sp)); + Error error (m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, + filename, + target_triple, + add_dependent_modules, + nullptr, + target_sp)); sb_target.SetSP (target_sp); } @@ -689,12 +674,12 @@ SBDebugger::CreateTargetWithFileAndArch (const char *filename, const char *arch_ Error error; const bool add_dependent_modules = true; - error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, - filename, - arch_cstr, - add_dependent_modules, - NULL, - target_sp); + error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, + filename, + arch_cstr, + add_dependent_modules, + nullptr, + target_sp); if (error.Success()) { @@ -720,12 +705,12 @@ SBDebugger::CreateTarget (const char *filename) { Error error; const bool add_dependent_modules = true; - error = m_opaque_sp->GetTargetList().CreateTarget (*m_opaque_sp, - filename, - NULL, - add_dependent_modules, - NULL, - target_sp); + error = m_opaque_sp->GetTargetList().CreateTarget(*m_opaque_sp, + filename, + nullptr, + add_dependent_modules, + nullptr, + target_sp); if (error.Success()) { @@ -767,6 +752,7 @@ SBDebugger::DeleteTarget (lldb::SBTarget &target) return result; } + SBTarget SBDebugger::GetTargetAtIndex (uint32_t idx) { @@ -813,7 +799,7 @@ SBDebugger::FindTargetWithFileAndArch (const char *filename, const char *arch_na { // No need to lock, the target list is thread safe ArchSpec arch (arch_name, m_opaque_sp->GetPlatformList().GetSelectedPlatform().get()); - TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture (FileSpec(filename, false), arch_name ? &arch : NULL)); + TargetSP target_sp (m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(FileSpec(filename, false), arch_name ? &arch : nullptr)); sb_target.SetSP (target_sp); } return sb_target; @@ -831,7 +817,6 @@ SBDebugger::FindTargetWithLLDBProcess (const ProcessSP &process_sp) return sb_target; } - uint32_t SBDebugger::GetNumTargets () { @@ -1000,6 +985,17 @@ SBDebugger::RunCommandInterpreter (bool auto_handle_events, } } +SBError +SBDebugger::RunREPL (lldb::LanguageType language, const char *repl_options) +{ + SBError error; + if (m_opaque_sp) + error.ref() = m_opaque_sp->RunREPL(language, repl_options); + else + error.SetErrorString ("invalid debugger"); + return error; +} + void SBDebugger::reset (const DebuggerSP &debugger_sp) { @@ -1039,10 +1035,7 @@ SBDebugger::FindDebuggerWithID (int id) const char * SBDebugger::GetInstanceName() { - if (m_opaque_sp) - return m_opaque_sp->GetInstanceName().AsCString(); - else - return NULL; + return (m_opaque_sp ? m_opaque_sp->GetInstanceName().AsCString() : nullptr); } SBError @@ -1098,11 +1091,9 @@ SBDebugger::GetInternalVariableValue (const char *var_name, const char *debugger } uint32_t -SBDebugger::GetTerminalWidth () const +SBDebugger::GetTerminalWidth() const { - if (m_opaque_sp) - return m_opaque_sp->GetTerminalWidth (); - return 0; + return (m_opaque_sp ? m_opaque_sp->GetTerminalWidth() : 0); } void @@ -1122,9 +1113,7 @@ SBDebugger::GetPrompt() const static_cast(m_opaque_sp.get()), (m_opaque_sp ? m_opaque_sp->GetPrompt() : "")); - if (m_opaque_sp) - return m_opaque_sp->GetPrompt (); - return 0; + return (m_opaque_sp ? m_opaque_sp->GetPrompt() : nullptr); } void @@ -1133,14 +1122,11 @@ SBDebugger::SetPrompt (const char *prompt) if (m_opaque_sp) m_opaque_sp->SetPrompt (prompt); } - ScriptLanguage SBDebugger::GetScriptLanguage() const { - if (m_opaque_sp) - return m_opaque_sp->GetScriptLanguage (); - return eScriptLanguageNone; + return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone); } void @@ -1153,35 +1139,27 @@ SBDebugger::SetScriptLanguage (ScriptLanguage script_lang) } bool -SBDebugger::SetUseExternalEditor (bool value) +SBDebugger::SetUseExternalEditor(bool value) { - if (m_opaque_sp) - return m_opaque_sp->SetUseExternalEditor (value); - return false; + return (m_opaque_sp ? m_opaque_sp->SetUseExternalEditor(value) : false); } bool -SBDebugger::GetUseExternalEditor () +SBDebugger::GetUseExternalEditor() { - if (m_opaque_sp) - return m_opaque_sp->GetUseExternalEditor (); - return false; + return (m_opaque_sp ? m_opaque_sp->GetUseExternalEditor() : false); } bool -SBDebugger::SetUseColor (bool value) +SBDebugger::SetUseColor(bool value) { - if (m_opaque_sp) - return m_opaque_sp->SetUseColor (value); - return false; + return (m_opaque_sp ? m_opaque_sp->SetUseColor(value) : false); } bool -SBDebugger::GetUseColor () const +SBDebugger::GetUseColor() const { - if (m_opaque_sp) - return m_opaque_sp->GetUseColor (); - return false; + return (m_opaque_sp ? m_opaque_sp->GetUseColor() : false); } bool @@ -1204,12 +1182,9 @@ SBDebugger::GetDescription (SBStream &description) user_id_t SBDebugger::GetID() { - if (m_opaque_sp) - return m_opaque_sp->GetID(); - return LLDB_INVALID_UID; + return (m_opaque_sp ? m_opaque_sp->GetID() : LLDB_INVALID_UID); } - SBError SBDebugger::SetCurrentPlatform (const char *platform_name_cstr) { @@ -1267,11 +1242,9 @@ SBDebugger::SetCurrentPlatformSDKRoot (const char *sysroot) } bool -SBDebugger::GetCloseInputOnEOF () const +SBDebugger::GetCloseInputOnEOF() const { - if (m_opaque_sp) - return m_opaque_sp->GetCloseInputOnEOF (); - return false; + return (m_opaque_sp ? m_opaque_sp->GetCloseInputOnEOF() : false); } void @@ -1295,6 +1268,16 @@ SBDebugger::GetCategory (const char* category_name) return SBTypeCategory(); } +SBTypeCategory +SBDebugger::GetCategory (lldb::LanguageType lang_type) +{ + TypeCategoryImplSP category_sp; + if (DataVisualization::Categories::GetCategory(lang_type, category_sp)) + return SBTypeCategory(category_sp); + else + return SBTypeCategory(); +} + SBTypeCategory SBDebugger::CreateCategory (const char* category_name) { @@ -1349,7 +1332,7 @@ SBDebugger::GetFormatForType (SBTypeNameSpecifier type_name) SBTypeSummary SBDebugger::GetSummaryForType (SBTypeNameSpecifier type_name) { - if (type_name.IsValid() == false) + if (!type_name.IsValid()) return SBTypeSummary(); return SBTypeSummary(DataVisualization::GetSummaryForType(type_name.GetSP())); } @@ -1358,7 +1341,7 @@ SBDebugger::GetSummaryForType (SBTypeNameSpecifier type_name) SBTypeFilter SBDebugger::GetFilterForType (SBTypeNameSpecifier type_name) { - if (type_name.IsValid() == false) + if (!type_name.IsValid()) return SBTypeFilter(); return SBTypeFilter(DataVisualization::GetFilterForType(type_name.GetSP())); } @@ -1367,7 +1350,7 @@ SBDebugger::GetFilterForType (SBTypeNameSpecifier type_name) SBTypeSynthetic SBDebugger::GetSyntheticForType (SBTypeNameSpecifier type_name) { - if (type_name.IsValid() == false) + if (!type_name.IsValid()) return SBTypeSynthetic(); return SBTypeSynthetic(DataVisualization::GetSyntheticForType(type_name.GetSP())); } @@ -1380,8 +1363,7 @@ SBDebugger::EnableLog (const char *channel, const char **categories) { uint32_t log_options = LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; StreamString errors; - return m_opaque_sp->EnableLog (channel, categories, NULL, log_options, errors); - + return m_opaque_sp->EnableLog(channel, categories, nullptr, log_options, errors); } else return false; @@ -1395,5 +1377,3 @@ SBDebugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *bato return m_opaque_sp->SetLoggingCallback (log_callback, baton); } } - - diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp index 08a5822cb781..02a215beb07d 100644 --- a/source/API/SBFrame.cpp +++ b/source/API/SBFrame.cpp @@ -7,10 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "lldb/API/SBFrame.h" - -#include +// C Includes +// C++ Includes #include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/API/SBFrame.h" #include "lldb/lldb-types.h" @@ -21,8 +25,8 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" @@ -50,7 +54,6 @@ using namespace lldb; using namespace lldb_private; - SBFrame::SBFrame () : m_opaque_sp (new ExecutionContextRef()) { @@ -76,6 +79,8 @@ SBFrame::SBFrame(const SBFrame &rhs) : { } +SBFrame::~SBFrame() = default; + const SBFrame & SBFrame::operator = (const SBFrame &rhs) { @@ -84,16 +89,10 @@ SBFrame::operator = (const SBFrame &rhs) return *this; } -SBFrame::~SBFrame() -{ -} - StackFrameSP SBFrame::GetFrameSP() const { - if (m_opaque_sp) - return m_opaque_sp->GetFrameSP(); - return StackFrameSP(); + return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP()); } void @@ -105,7 +104,7 @@ SBFrame::SetFrameSP (const StackFrameSP &lldb_object_sp) bool SBFrame::IsValid() const { - return GetFrameSP().get() != NULL; + return GetFrameSP().get() != nullptr; } SBSymbolContext @@ -116,7 +115,7 @@ SBFrame::GetSymbolContext (uint32_t resolve_scope) const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -159,7 +158,7 @@ SBFrame::GetModule () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -202,7 +201,7 @@ SBFrame::GetCompileUnit () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -243,7 +242,7 @@ SBFrame::GetFunction () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -284,7 +283,7 @@ SBFrame::GetSymbol () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -324,7 +323,7 @@ SBFrame::GetBlock () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -364,7 +363,7 @@ SBFrame::GetFrameBlock () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); Process *process = exe_ctx.GetProcessPtr(); @@ -405,7 +404,7 @@ SBFrame::GetLineEntry () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -464,7 +463,6 @@ SBFrame::GetCFA () const return LLDB_INVALID_ADDRESS; } - addr_t SBFrame::GetPC () const { @@ -473,7 +471,7 @@ SBFrame::GetPC () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -484,7 +482,7 @@ SBFrame::GetPC () const frame = exe_ctx.GetFramePtr(); if (frame) { - addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress (target); + addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress (target, eAddressClassCode); } else { @@ -514,7 +512,7 @@ SBFrame::SetPC (addr_t new_pc) Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -555,7 +553,7 @@ SBFrame::GetSP () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -587,7 +585,6 @@ SBFrame::GetSP () const return addr; } - addr_t SBFrame::GetFP () const { @@ -596,7 +593,7 @@ SBFrame::GetFP () const Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -628,7 +625,6 @@ SBFrame::GetFP () const return addr; } - SBAddress SBFrame::GetPCAddress () const { @@ -696,7 +692,7 @@ SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dyn SBValue sb_value; Mutex::Locker api_locker; Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - if (var_path == NULL || var_path[0] == '\0') + if (var_path == nullptr || var_path[0] == '\0') { if (log) log->Printf ("SBFrame::GetValueForVariablePath called with empty variable path."); @@ -705,7 +701,7 @@ SBFrame::GetValueForVariablePath (const char *var_path, DynamicValueType use_dyn ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -762,7 +758,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic) VariableSP var_sp; SBValue sb_value; - if (name == NULL || name[0] == '\0') + if (name == nullptr || name[0] == '\0') { if (log) log->Printf ("SBFrame::FindVariable called with empty name"); @@ -773,7 +769,7 @@ SBFrame::FindVariable (const char *name, lldb::DynamicValueType use_dynamic) Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -850,7 +846,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBValue sb_value; - if (name == NULL || name[0] == '\0') + if (name == nullptr || name[0] == '\0') { if (log) log->Printf ("SBFrame::FindValue called with empty name."); @@ -861,7 +857,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -956,7 +952,7 @@ SBFrame::FindValue (const char *name, ValueType value_type, lldb::DynamicValueTy case eValueTypeConstResult: // constant result variables { ConstString const_name(name); - ClangExpressionVariableSP expr_var_sp (target->GetPersistentVariables().GetVariable (const_name)); + ExpressionVariableSP expr_var_sp (target->GetPersistentVariable (const_name)); if (expr_var_sp) { value_sp = expr_var_sp->GetValueObject(); @@ -1035,11 +1031,11 @@ const char * SBFrame::Disassemble () const { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - const char *disassembly = NULL; + const char *disassembly = nullptr; Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1072,7 +1068,6 @@ SBFrame::Disassemble () const return disassembly; } - SBValueList SBFrame::GetVariables (bool arguments, bool locals, @@ -1130,7 +1125,7 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options) Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); const bool statics = options.GetIncludeStatics(); @@ -1156,7 +1151,7 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options) if (frame) { size_t i; - VariableList *variable_list = NULL; + VariableList *variable_list = nullptr; variable_list = frame->GetVariableList(true); if (variable_list) { @@ -1194,9 +1189,9 @@ SBFrame::GetVariables (const lldb::SBVariablesOptions& options) ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues)); - if (false == include_runtime_support_values && - valobj_sp && - true == valobj_sp->IsRuntimeSupportValue()) + if (!include_runtime_support_values && + valobj_sp != nullptr && + valobj_sp->IsRuntimeSupportValue()) continue; SBValue value_sb; @@ -1238,7 +1233,7 @@ SBFrame::GetRegisters () Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1290,7 +1285,7 @@ SBFrame::FindRegister (const char *name) Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1394,6 +1389,10 @@ SBFrame::EvaluateExpression (const char *expr) lldb::DynamicValueType fetch_dynamic_value = frame->CalculateTarget()->GetPreferDynamicValue(); options.SetFetchDynamicValue (fetch_dynamic_value); options.SetUnwindOnError (true); + if (target->GetLanguage() != eLanguageTypeUnknown) + options.SetLanguage(target->GetLanguage()); + else + options.SetLanguage(frame->GetLanguage()); return EvaluateExpression (expr, options); } return result; @@ -1405,6 +1404,13 @@ SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dyna SBExpressionOptions options; options.SetFetchDynamicValue (fetch_dynamic_value); options.SetUnwindOnError (true); + ExecutionContext exe_ctx(m_opaque_sp.get()); + StackFrame *frame = exe_ctx.GetFramePtr(); + Target *target = exe_ctx.GetTargetPtr(); + if (target && target->GetLanguage() != eLanguageTypeUnknown) + options.SetLanguage(target->GetLanguage()); + else if (frame) + options.SetLanguage(frame->GetLanguage()); return EvaluateExpression (expr, options); } @@ -1412,8 +1418,15 @@ SBValue SBFrame::EvaluateExpression (const char *expr, lldb::DynamicValueType fetch_dynamic_value, bool unwind_on_error) { SBExpressionOptions options; + ExecutionContext exe_ctx(m_opaque_sp.get()); options.SetFetchDynamicValue (fetch_dynamic_value); options.SetUnwindOnError (unwind_on_error); + StackFrame *frame = exe_ctx.GetFramePtr(); + Target *target = exe_ctx.GetTargetPtr(); + if (target && target->GetLanguage() != eLanguageTypeUnknown) + options.SetLanguage(target->GetLanguage()); + else if (frame) + options.SetLanguage(frame->GetLanguage()); return EvaluateExpression (expr, options); } @@ -1427,7 +1440,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option ExpressionResults exe_results = eExpressionSetupError; SBValue expr_result; - if (expr == NULL || expr[0] == '\0') + if (expr == nullptr || expr[0] == '\0') { if (log) log->Printf ("SBFrame::EvaluateExpression called with an empty expression"); @@ -1442,7 +1455,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option if (log) log->Printf ("SBFrame()::EvaluateExpression (expr=\"%s\")...", expr); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); @@ -1469,7 +1482,7 @@ SBFrame::EvaluateExpression (const char *expr, const SBExpressionOptions &option expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue()); if (target->GetDisplayExpressionsInCrashlogs()) - Host::SetCrashDescription (NULL); + Host::SetCrashDescription(nullptr); } else { @@ -1509,7 +1522,7 @@ SBFrame::IsInlined() const { Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ExecutionContext exe_ctx(m_opaque_sp.get()); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1523,7 +1536,7 @@ SBFrame::IsInlined() const Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; if (block) - return block->GetContainingInlinedBlock () != NULL; + return block->GetContainingInlinedBlock() != nullptr; } else { @@ -1551,9 +1564,9 @@ const char * SBFrame::GetFunctionName() const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - const char *name = NULL; + const char *name = nullptr; ExecutionContext exe_ctx(m_opaque_sp.get()); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1575,13 +1588,13 @@ SBFrame::GetFunctionName() const } } - if (name == NULL) + if (name == nullptr) { if (sc.function) name = sc.function->GetName().GetCString(); } - if (name == NULL) + if (name == nullptr) { if (sc.symbol) name = sc.symbol->GetName().GetCString(); @@ -1607,9 +1620,9 @@ const char * SBFrame::GetDisplayFunctionName() { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - const char *name = NULL; + const char *name = nullptr; ExecutionContext exe_ctx(m_opaque_sp.get()); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; Target *target = exe_ctx.GetTargetPtr(); Process *process = exe_ctx.GetProcessPtr(); if (target && process) @@ -1631,13 +1644,13 @@ SBFrame::GetDisplayFunctionName() } } - if (name == NULL) + if (name == nullptr) { if (sc.function) name = sc.function->GetDisplayName().GetCString(); } - if (name == NULL) + if (name == nullptr) { if (sc.symbol) name = sc.symbol->GetDisplayName().GetCString(); diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp index 2ec6072b51eb..2d03d53fd9f7 100644 --- a/source/API/SBFunction.cpp +++ b/source/API/SBFunction.cpp @@ -16,6 +16,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" @@ -216,6 +217,24 @@ SBFunction::GetEndAddress () return addr; } +const char * +SBFunction::GetArgumentName (uint32_t arg_idx) +{ + if (m_opaque_ptr) + { + Block &block = m_opaque_ptr->GetBlock(true); + VariableListSP variable_list_sp = block.GetBlockVariableList(true); + if (variable_list_sp) + { + VariableList arguments; + variable_list_sp->AppendVariablesWithScope (eValueTypeVariableArgument, arguments, true); + lldb::VariableSP variable_sp = arguments.GetVariableAtIndex(arg_idx); + if (variable_sp) + return variable_sp->GetName().GetCString(); + } + } + return nullptr; +} uint32_t SBFunction::GetPrologueByteSize () @@ -258,4 +277,13 @@ SBFunction::GetLanguage () return lldb::eLanguageTypeUnknown; } - +bool +SBFunction::GetIsOptimized () +{ + if (m_opaque_ptr) + { + if (m_opaque_ptr->GetCompileUnit()) + return m_opaque_ptr->GetCompileUnit()->GetIsOptimized(); + } + return false; +} diff --git a/source/API/SBLanguageRuntime.cpp b/source/API/SBLanguageRuntime.cpp index 93a54cd76dff..743343e48589 100644 --- a/source/API/SBLanguageRuntime.cpp +++ b/source/API/SBLanguageRuntime.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/API/SBLanguageRuntime.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; @@ -16,11 +16,11 @@ using namespace lldb_private; lldb::LanguageType SBLanguageRuntime::GetLanguageTypeFromString (const char *string) { - return LanguageRuntime::GetLanguageTypeFromString(string); + return Language::GetLanguageTypeFromString(string); } const char * SBLanguageRuntime::GetNameForLanguageType (lldb::LanguageType language) { - return LanguageRuntime::GetNameForLanguageType(language); + return Language::GetNameForLanguageType(language); } diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp index 0249a7edcd2b..a810940f301f 100644 --- a/source/API/SBModule.cpp +++ b/source/API/SBModule.cpp @@ -20,10 +20,10 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Symtab.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/Target.h" @@ -521,7 +521,11 @@ SBModule::FindFirstType (const char *name_cstr) sb_type = SBType (module_sp->FindFirstType(sc, name, exact_match)); if (!sb_type.IsValid()) - sb_type = SBType (ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), name)); + { + TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system) + sb_type = SBType (type_system->GetBuiltinTypeByName(name)); + } } return sb_type; } @@ -531,7 +535,11 @@ SBModule::GetBasicType(lldb::BasicType type) { ModuleSP module_sp (GetSP ()); if (module_sp) - return SBType (ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), type)); + { + TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system) + return SBType (type_system->GetBasicTypeFromAST(type)); + } return SBType(); } @@ -564,9 +572,13 @@ SBModule::FindTypes (const char *type) } else { - SBType sb_type(ClangASTContext::GetBasicType (module_sp->GetClangASTContext().getASTContext(), name)); - if (sb_type.IsValid()) - retval.Append(sb_type); + TypeSystem *type_system = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system) + { + CompilerType compiler_type = type_system->GetBuiltinTypeByName(name); + if (compiler_type) + retval.Append(SBType(compiler_type)); + } } } diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp index 97ffcf149750..b8dc01ba7811 100644 --- a/source/API/SBPlatform.cpp +++ b/source/API/SBPlatform.cpp @@ -189,7 +189,7 @@ SBPlatformShellCommand::~SBPlatformShellCommand() void SBPlatformShellCommand::Clear() { - m_opaque_ptr->m_output = std::move(std::string()); + m_opaque_ptr->m_output = std::string(); m_opaque_ptr->m_status = 0; m_opaque_ptr->m_signo = 0; } diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 01bfaf9aff01..dceadeca69e5 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" @@ -409,7 +410,7 @@ SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) - log->Printf ("SBProcess(%p)::GetProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64, + log->Printf ("SBProcess(%p)::GetAsyncProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64, static_cast(process_sp.get()), static_cast(bytes_read), dst, static_cast(dst_len), @@ -1287,7 +1288,15 @@ SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const } uint32_t -SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error) +SBProcess::LoadImage (lldb::SBFileSpec &sb_remote_image_spec, lldb::SBError &sb_error) +{ + return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error); +} + +uint32_t +SBProcess::LoadImage (const lldb::SBFileSpec &sb_local_image_spec, + const lldb::SBFileSpec &sb_remote_image_spec, + lldb::SBError &sb_error) { ProcessSP process_sp(GetSP()); if (process_sp) @@ -1296,7 +1305,11 @@ SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error) if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); - return process_sp->LoadImage (*sb_image_spec, sb_error.ref()); + PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); + return platform_sp->LoadImage (process_sp.get(), + *sb_local_image_spec, + *sb_remote_image_spec, + sb_error.ref()); } else { @@ -1321,7 +1334,8 @@ SBProcess::UnloadImage (uint32_t image_token) if (stop_locker.TryLock(&process_sp->GetRunLock())) { Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); - sb_error.SetError (process_sp->UnloadImage (image_token)); + PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); + sb_error.SetError (platform_sp->UnloadImage (process_sp.get(), image_token)); } else { @@ -1425,3 +1439,27 @@ SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type) return runtime_sp->IsActive(); } + +lldb::SBError +SBProcess::SaveCore(const char *file_name) +{ + lldb::SBError error; + ProcessSP process_sp(GetSP()); + if (!process_sp) + { + error.SetErrorString("SBProcess is invalid"); + return error; + } + + Mutex::Locker api_locker(process_sp->GetTarget().GetAPIMutex()); + + if (process_sp->GetState() != eStateStopped) + { + error.SetErrorString("the process is not stopped"); + return error; + } + + FileSpec core_file(file_name, false); + error.ref() = PluginManager::SaveCore(process_sp, core_file); + return error; +} diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp index f50334f74189..f3be3be6a10d 100644 --- a/source/API/SBStream.cpp +++ b/source/API/SBStream.cpp @@ -23,6 +23,13 @@ SBStream::SBStream () : { } +SBStream::SBStream (SBStream &&rhs) : + m_opaque_ap (std::move(rhs.m_opaque_ap)), + m_is_file (rhs.m_is_file) +{ +} + + SBStream::~SBStream () { } diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index 6597d4e77c73..c7595c3c39fb 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -52,6 +52,7 @@ #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/Language.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" @@ -847,11 +848,11 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, { FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware); + *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, skip_prologue, internal, hardware); } else { - *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware); + *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, skip_prologue, internal, hardware); } } @@ -869,7 +870,7 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const SBFileSpecList &comp_unit_list) { uint32_t name_type_mask = eFunctionNameTypeAuto; - return BreakpointCreateByName (symbol_name, name_type_mask, module_list, comp_unit_list); + return BreakpointCreateByName (symbol_name, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list); } lldb::SBBreakpoint @@ -877,6 +878,16 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, uint32_t name_type_mask, const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) +{ + return BreakpointCreateByName (symbol_name, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list); +} + +lldb::SBBreakpoint +SBTarget::BreakpointCreateByName (const char *symbol_name, + uint32_t name_type_mask, + LanguageType symbol_language, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -892,6 +903,7 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, comp_unit_list.get(), symbol_name, name_type_mask, + symbol_language, skip_prologue, internal, hardware); @@ -911,6 +923,17 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], uint32_t name_type_mask, const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) +{ + return BreakpointCreateByNames(symbol_names, num_names, name_type_mask, eLanguageTypeUnknown, module_list, comp_unit_list); +} + +lldb::SBBreakpoint +SBTarget::BreakpointCreateByNames (const char *symbol_names[], + uint32_t num_names, + uint32_t name_type_mask, + LanguageType symbol_language, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -923,13 +946,14 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; *sb_bp = target_sp->CreateBreakpoint (module_list.get(), - comp_unit_list.get(), - symbol_names, - num_names, - name_type_mask, - skip_prologue, - internal, - hardware); + comp_unit_list.get(), + symbol_names, + num_names, + name_type_mask, + symbol_language, + skip_prologue, + internal, + hardware); } if (log) @@ -958,6 +982,30 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], SBBreakpoint SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name) +{ + SBFileSpecList module_spec_list; + SBFileSpecList comp_unit_list; + if (module_name && module_name[0]) + { + module_spec_list.Append (FileSpec (module_name, false)); + + } + return BreakpointCreateByRegex (symbol_name_regex, eLanguageTypeUnknown, module_spec_list, comp_unit_list); +} + +lldb::SBBreakpoint +SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) +{ + return BreakpointCreateByRegex (symbol_name_regex, eLanguageTypeUnknown, module_list, comp_unit_list); +} + +lldb::SBBreakpoint +SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, + LanguageType symbol_language, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -970,75 +1018,72 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const bool internal = false; const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; - - if (module_name && module_name[0]) - { - FileSpecList module_spec_list; - module_spec_list.Append (FileSpec (module_name, false)); - - *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware); - } - else - { - *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal, hardware); - } + + *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, symbol_language, skip_prologue, internal, hardware); } if (log) - log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)", + log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)", static_cast(target_sp.get()), symbol_name_regex, - module_name, static_cast(sb_bp.get())); + static_cast(sb_bp.get())); return sb_bp; } -lldb::SBBreakpoint -SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, - const SBFileSpecList &module_list, - const SBFileSpecList &comp_unit_list) +SBBreakpoint +SBTarget::BreakpointCreateByAddress (addr_t address) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBBreakpoint sb_bp; TargetSP target_sp(GetSP()); - if (target_sp && symbol_name_regex && symbol_name_regex[0]) + if (target_sp) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); - RegularExpression regexp(symbol_name_regex); - const bool internal = false; const bool hardware = false; - const LazyBool skip_prologue = eLazyBoolCalculate; - - *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware); + *sb_bp = target_sp->CreateBreakpoint (address, false, hardware); } if (log) - log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)", - static_cast(target_sp.get()), symbol_name_regex, + log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)", + static_cast(target_sp.get()), + static_cast(address), static_cast(sb_bp.get())); return sb_bp; } SBBreakpoint -SBTarget::BreakpointCreateByAddress (addr_t address) +SBTarget::BreakpointCreateBySBAddress (SBAddress &sb_address) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBBreakpoint sb_bp; TargetSP target_sp(GetSP()); + if (!sb_address.IsValid()) + { + if (log) + log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress called with invalid address", + static_cast(target_sp.get())); + return sb_bp; + } + if (target_sp) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); const bool hardware = false; - *sb_bp = target_sp->CreateBreakpoint (address, false, hardware); + *sb_bp = target_sp->CreateBreakpoint (sb_address.ref(), false, hardware); } if (log) - log->Printf ("SBTarget(%p)::BreakpointCreateByAddress (address=%" PRIu64 ") => SBBreakpoint(%p)", + { + SBStream s; + sb_address.GetDescription(s); + log->Printf ("SBTarget(%p)::BreakpointCreateBySBAddress (address=%s) => SBBreakpoint(%p)", static_cast(target_sp.get()), - static_cast(address), + s.GetData(), static_cast(sb_bp.get())); + } return sb_bp; } @@ -1131,7 +1176,7 @@ SBTarget::BreakpointCreateForException (lldb::LanguageType language, if (log) log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: %s throw: %s) => SBBreakpoint(%p)", static_cast(target_sp.get()), - LanguageRuntime::GetNameForLanguageType(language), + Language::GetNameForLanguageType(language), catch_bp ? "on" : "off", throw_bp ? "on" : "off", static_cast(sb_bp.get())); @@ -1344,7 +1389,7 @@ SBTarget::WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, S // Target::CreateWatchpoint() is thread safe. Error cw_error; // This API doesn't take in a type, so we can't figure out what it is. - ClangASTType *type = NULL; + CompilerType *type = NULL; watchpoint_sp = target_sp->CreateWatchpoint(addr, size, type, watch_type, cw_error); error.SetError(cw_error); sb_watchpoint.SetSP (watchpoint_sp); @@ -1398,7 +1443,7 @@ SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type) { lldb::addr_t load_addr(addr.GetLoadAddress(*this)); ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); - ClangASTType ast_type(type.GetSP()->GetClangASTType(true)); + CompilerType ast_type(type.GetSP()->GetCompilerType(true)); new_value_sp = ValueObject::CreateValueObjectFromAddress(name, load_addr, exe_ctx, ast_type); } sb_value.SetSP(new_value_sp); @@ -1425,7 +1470,7 @@ SBTarget::CreateValueFromData (const char *name, lldb::SBData data, lldb::SBType { DataExtractorSP extractor(*data); ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); - ClangASTType ast_type(type.GetSP()->GetClangASTType(true)); + CompilerType ast_type(type.GetSP()->GetCompilerType(true)); new_value_sp = ValueObject::CreateValueObjectFromData(name, *extractor, exe_ctx, ast_type); } sb_value.SetSP(new_value_sp); @@ -1806,7 +1851,7 @@ SBTarget::FindFirstType (const char* typename_cstr) if (objc_decl_vendor->FindDecls(const_typename, true, 1, decls) > 0) { - if (ClangASTType type = ClangASTContext::GetTypeForDecl(decls[0])) + if (CompilerType type = ClangASTContext::GetTypeForDecl(decls[0])) { return SBType(type); } @@ -1886,7 +1931,7 @@ SBTarget::FindTypes (const char* typename_cstr) { for (clang::NamedDecl *decl : decls) { - if (ClangASTType type = ClangASTContext::GetTypeForDecl(decl)) + if (CompilerType type = ClangASTContext::GetTypeForDecl(decl)) { sb_type_list.Append(SBType(type)); } diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 42b5c9affe50..2f3887ebce3a 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -747,7 +747,7 @@ SBThread::StepOver (lldb::RunMode stop_other_threads) const LazyBool avoid_no_debug = eLazyBoolCalculate; SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, - sc.line_entry.range, + sc.line_entry, sc, stop_other_threads, avoid_no_debug); @@ -799,7 +799,7 @@ SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads) const LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate; SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, - sc.line_entry.range, + sc.line_entry, sc, target_name, stop_other_threads, @@ -826,7 +826,6 @@ SBThread::StepOut () Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); - if (log) log->Printf ("SBThread(%p)::StepOut ()", static_cast(exe_ctx.GetThreadPtr())); @@ -861,6 +860,14 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame) Mutex::Locker api_locker; ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); + if (!sb_frame.IsValid()) + { + if (log) + log->Printf("SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.", + static_cast(exe_ctx.GetThreadPtr())); + return; + } + StackFrameSP frame_sp (sb_frame.GetFrameSP()); if (log) { @@ -877,6 +884,13 @@ SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame) bool abort_other_plans = false; bool stop_other_threads = false; Thread *thread = exe_ctx.GetThreadPtr(); + if (sb_frame.GetThread().GetThreadID() != thread->GetID()) + { + log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.", + static_cast(exe_ctx.GetThreadPtr()), + sb_frame.GetThread().GetThreadID(), + thread->GetID()); + } ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index 31a4eba8bf33..4922b491a227 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -13,24 +13,24 @@ #include "lldb/API/SBStream.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Mangled.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeSystem.h" -#include "clang/AST/Decl.h" +#include "llvm/ADT/APSInt.h" using namespace lldb; using namespace lldb_private; -using namespace clang; SBType::SBType() : m_opaque_sp() { } -SBType::SBType (const ClangASTType &type) : - m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(), +SBType::SBType (const CompilerType &type) : + m_opaque_sp(new TypeImpl(CompilerType(type.GetTypeSystem(), type.GetOpaqueQualType()))) { } @@ -143,7 +143,7 @@ SBType::GetByteSize() if (!IsValid()) return 0; - return m_opaque_sp->GetClangASTType(false).GetByteSize(nullptr); + return m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr); } @@ -152,7 +152,7 @@ SBType::IsPointerType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsPointerType(); + return m_opaque_sp->GetCompilerType(true).IsPointerType(); } bool @@ -160,7 +160,7 @@ SBType::IsArrayType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsArrayType(nullptr, nullptr, nullptr); + return m_opaque_sp->GetCompilerType(true).IsArrayType(nullptr, nullptr, nullptr); } bool @@ -168,7 +168,7 @@ SBType::IsVectorType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsVectorType(nullptr, nullptr); + return m_opaque_sp->GetCompilerType(true).IsVectorType(nullptr, nullptr); } bool @@ -176,7 +176,7 @@ SBType::IsReferenceType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsReferenceType(); + return m_opaque_sp->GetCompilerType(true).IsReferenceType(); } SBType @@ -225,7 +225,7 @@ SBType::GetArrayElementType() { if (!IsValid()) return SBType(); - return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetClangASTType(true).GetArrayElementType()))); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCompilerType(true).GetArrayElementType()))); } SBType @@ -234,8 +234,8 @@ SBType::GetVectorElementType () SBType type_sb; if (IsValid()) { - ClangASTType vector_element_type; - if (m_opaque_sp->GetClangASTType(true).IsVectorType(&vector_element_type, nullptr)) + CompilerType vector_element_type; + if (m_opaque_sp->GetCompilerType(true).IsVectorType(&vector_element_type, nullptr)) type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type))); } return type_sb; @@ -246,7 +246,7 @@ SBType::IsFunctionType () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsFunctionType(); + return m_opaque_sp->GetCompilerType(true).IsFunctionType(); } bool @@ -254,7 +254,7 @@ SBType::IsPolymorphicClass () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass(); + return m_opaque_sp->GetCompilerType(true).IsPolymorphicClass(); } bool @@ -262,7 +262,15 @@ SBType::IsTypedefType () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(true).IsTypedefType(); + return m_opaque_sp->GetCompilerType(true).IsTypedefType(); +} + +bool +SBType::IsAnonymousType () +{ + if (!IsValid()) + return false; + return m_opaque_sp->GetCompilerType(true).IsAnonymousType(); } lldb::SBType @@ -270,9 +278,9 @@ SBType::GetFunctionReturnType () { if (IsValid()) { - ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType()); - if (return_clang_type.IsValid()) - return SBType(return_clang_type); + CompilerType return_type (m_opaque_sp->GetCompilerType(true).GetFunctionReturnType()); + if (return_type.IsValid()) + return SBType(return_type); } return lldb::SBType(); } @@ -283,7 +291,7 @@ SBType::GetFunctionArgumentTypes () SBTypeList sb_type_list; if (IsValid()) { - ClangASTType func_type(m_opaque_sp->GetClangASTType(true)); + CompilerType func_type(m_opaque_sp->GetCompilerType(true)); size_t count = func_type.GetNumberOfFunctionArguments(); for (size_t i = 0; i < count; @@ -300,7 +308,7 @@ SBType::GetNumberOfMemberFunctions () { if (IsValid()) { - return m_opaque_sp->GetClangASTType(true).GetNumMemberFunctions(); + return m_opaque_sp->GetCompilerType(true).GetNumMemberFunctions(); } return 0; } @@ -310,7 +318,7 @@ SBType::GetMemberFunctionAtIndex (uint32_t idx) { SBTypeMemberFunction sb_func_type; if (IsValid()) - sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetClangASTType(true).GetMemberFunctionAtIndex(idx))); + sb_func_type.reset(new TypeMemberFunctionImpl(m_opaque_sp->GetCompilerType(true).GetMemberFunctionAtIndex(idx))); return sb_func_type; } @@ -335,15 +343,15 @@ lldb::BasicType SBType::GetBasicType() { if (IsValid()) - return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration (); + return m_opaque_sp->GetCompilerType(false).GetBasicTypeEnumeration (); return eBasicTypeInvalid; } SBType SBType::GetBasicType(lldb::BasicType basic_type) { - if (IsValid()) - return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type)); + if (IsValid() && m_opaque_sp->IsValid()) + return SBType(m_opaque_sp->GetTypeSystem(false)->GetBasicTypeFromAST(basic_type)); return SBType(); } @@ -351,7 +359,7 @@ uint32_t SBType::GetNumberOfDirectBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses(); + return m_opaque_sp->GetCompilerType(true).GetNumDirectBaseClasses(); return 0; } @@ -359,7 +367,7 @@ uint32_t SBType::GetNumberOfVirtualBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses(); + return m_opaque_sp->GetCompilerType(true).GetNumVirtualBaseClasses(); return 0; } @@ -367,7 +375,7 @@ uint32_t SBType::GetNumberOfFields () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetNumFields(); + return m_opaque_sp->GetCompilerType(true).GetNumFields(); return 0; } @@ -394,16 +402,10 @@ SBType::GetDirectBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); - if (this_type.IsValid()) - { - uint32_t bit_offset = 0; - ClangASTType base_class_type (this_type.GetDirectBaseClassAtIndex(idx, &bit_offset)); - if (base_class_type.IsValid()) - { - sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); - } - } + uint32_t bit_offset = 0; + CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetDirectBaseClassAtIndex(idx, &bit_offset); + if (base_class_type.IsValid()) + sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); } return sb_type_member; @@ -415,16 +417,10 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); - if (this_type.IsValid()) - { - uint32_t bit_offset = 0; - ClangASTType base_class_type (this_type.GetVirtualBaseClassAtIndex(idx, &bit_offset)); - if (base_class_type.IsValid()) - { - sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); - } - } + uint32_t bit_offset = 0; + CompilerType base_class_type = m_opaque_sp->GetCompilerType (true).GetVirtualBaseClassAtIndex(idx, &bit_offset); + if (base_class_type.IsValid()) + sb_type_member.reset (new TypeMemberImpl (TypeImplSP(new TypeImpl(base_class_type)), bit_offset)); } return sb_type_member; } @@ -435,16 +431,14 @@ SBType::GetEnumMembers () SBTypeEnumMemberList sb_enum_member_list; if (IsValid()) { - const clang::EnumDecl *enum_decl = m_opaque_sp->GetClangASTType(true).GetFullyUnqualifiedType().GetAsEnumDecl(); - if (enum_decl) + CompilerType this_type (m_opaque_sp->GetCompilerType (true)); + if (this_type.IsValid()) { - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - SBTypeEnumMember enum_member; - enum_member.reset(new TypeEnumMemberImpl(*enum_pos, ClangASTType(m_opaque_sp->GetClangASTContext(true), enum_decl->getIntegerType()))); + this_type.ForEachEnumerator([&sb_enum_member_list] (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value) -> bool { + SBTypeEnumMember enum_member (lldb::TypeEnumMemberImplSP (new TypeEnumMemberImpl(lldb::TypeImplSP(new TypeImpl(integer_type)), name, value))); sb_enum_member_list.Append(enum_member); - } + return true; // Keep iterating + }); } } return sb_enum_member_list; @@ -456,14 +450,14 @@ SBType::GetFieldAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType (false)); + CompilerType this_type (m_opaque_sp->GetCompilerType (false)); if (this_type.IsValid()) { uint64_t bit_offset = 0; uint32_t bitfield_bit_size = 0; bool is_bitfield = false; std::string name_sstr; - ClangASTType field_type (this_type.GetFieldAtIndex (idx, + CompilerType field_type (this_type.GetFieldAtIndex (idx, name_sstr, &bit_offset, &bitfield_bit_size, @@ -489,7 +483,7 @@ SBType::IsTypeComplete() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType(false).IsCompleteType(); + return m_opaque_sp->GetCompilerType(false).IsCompleteType(); } uint32_t @@ -497,7 +491,7 @@ SBType::GetTypeFlags () { if (!IsValid()) return 0; - return m_opaque_sp->GetClangASTType(true).GetTypeInfo(); + return m_opaque_sp->GetCompilerType(true).GetTypeInfo(); } const char* @@ -520,7 +514,7 @@ lldb::TypeClass SBType::GetTypeClass () { if (IsValid()) - return m_opaque_sp->GetClangASTType(true).GetTypeClass(); + return m_opaque_sp->GetCompilerType(true).GetTypeClass(); return lldb::eTypeClassInvalid; } @@ -528,7 +522,7 @@ uint32_t SBType::GetNumberOfTemplateArguments () { if (IsValid()) - return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments(); + return m_opaque_sp->GetCompilerType(false).GetNumTemplateArguments(); return 0; } @@ -538,7 +532,7 @@ SBType::GetTemplateArgumentType (uint32_t idx) if (IsValid()) { TemplateArgumentKind kind = eTemplateArgumentKindNull; - ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); + CompilerType template_arg_type = m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); if (template_arg_type.IsValid()) return SBType(template_arg_type); } @@ -551,7 +545,7 @@ SBType::GetTemplateArgumentKind (uint32_t idx) { TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) - m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); + m_opaque_sp->GetCompilerType(false).GetTemplateArgument(idx, kind); return kind; } @@ -791,6 +785,30 @@ SBTypeMemberFunction::GetName () return NULL; } +const char * +SBTypeMemberFunction::GetDemangledName () +{ + if (m_opaque_sp) + { + ConstString mangled_str = m_opaque_sp->GetMangledName(); + if (mangled_str) + { + Mangled mangled(mangled_str, true); + return mangled.GetDemangledName(mangled.GuessLanguage()).GetCString(); + } + } + return NULL; +} + +const char * +SBTypeMemberFunction::GetMangledName() +{ + if (m_opaque_sp) + return m_opaque_sp->GetMangledName().GetCString(); + return NULL; +} + + SBType SBTypeMemberFunction::GetType () { diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp index ee9553ca6abd..33dada8da39d 100644 --- a/source/API/SBTypeCategory.cpp +++ b/source/API/SBTypeCategory.cpp @@ -79,6 +79,29 @@ SBTypeCategory::GetName() return m_opaque_sp->GetName(); } +lldb::LanguageType +SBTypeCategory::GetLanguageAtIndex (uint32_t idx) +{ + if (IsValid()) + return m_opaque_sp->GetLanguageAtIndex(idx); + return lldb::eLanguageTypeUnknown; +} + +uint32_t +SBTypeCategory::GetNumLanguages () +{ + if (IsValid()) + return m_opaque_sp->GetNumLanguages(); + return 0; +} + +void +SBTypeCategory::AddLanguage (lldb::LanguageType language) +{ + if (IsValid()) + m_opaque_sp->AddLanguage(language); +} + uint32_t SBTypeCategory::GetNumFormats () { @@ -157,7 +180,7 @@ SBTypeCategory::GetFilterForType (SBTypeNameSpecifier spec) if (!spec.IsValid()) return SBTypeFilter(); - lldb::SyntheticChildrenSP children_sp; + lldb::TypeFilterImplSP children_sp; if (spec.IsRegex()) m_opaque_sp->GetRegexTypeFiltersContainer()->GetExact(ConstString(spec.GetName()), children_sp); diff --git a/source/API/SBTypeEnumMember.cpp b/source/API/SBTypeEnumMember.cpp index 47c57dd213fb..c23f7ea8c6ce 100644 --- a/source/API/SBTypeEnumMember.cpp +++ b/source/API/SBTypeEnumMember.cpp @@ -12,12 +12,11 @@ #include "lldb/API/SBTypeEnumMember.h" #include "lldb/API/SBStream.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" using namespace lldb; using namespace lldb_private; -using namespace clang; SBTypeEnumMember::SBTypeEnumMember() : m_opaque_sp() diff --git a/source/API/SBTypeNameSpecifier.cpp b/source/API/SBTypeNameSpecifier.cpp index c58747170b5a..6f6801099b7c 100644 --- a/source/API/SBTypeNameSpecifier.cpp +++ b/source/API/SBTypeNameSpecifier.cpp @@ -34,7 +34,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier (SBType type) : m_opaque_sp() { if (type.IsValid()) - m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType(true))); + m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetCompilerType(true))); } SBTypeNameSpecifier::SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs) : @@ -65,7 +65,7 @@ SBTypeNameSpecifier::GetType () { if (!IsValid()) return SBType(); - lldb_private::ClangASTType c_type = m_opaque_sp->GetClangASTType(); + lldb_private::CompilerType c_type = m_opaque_sp->GetCompilerType(); if (c_type.IsValid()) return SBType(c_type); return SBType(); diff --git a/source/API/SBTypeSummary.cpp b/source/API/SBTypeSummary.cpp index 2c114545419c..2985b7659547 100644 --- a/source/API/SBTypeSummary.cpp +++ b/source/API/SBTypeSummary.cpp @@ -8,16 +8,15 @@ //===----------------------------------------------------------------------===// #include "lldb/API/SBTypeSummary.h" - #include "lldb/API/SBStream.h" - +#include "lldb/API/SBValue.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "llvm/Support/Casting.h" + using namespace lldb; using namespace lldb_private; -#ifndef LLDB_DISABLE_PYTHON - SBTypeSummaryOptions::SBTypeSummaryOptions() { m_opaque_ap.reset(new TypeSummaryOptions()); @@ -147,6 +146,28 @@ SBTypeSummary::CreateWithScriptCode (const char* data, uint32_t options) return SBTypeSummary(TypeSummaryImplSP(new ScriptSummaryFormat(options, "", data))); } +SBTypeSummary +SBTypeSummary::CreateWithCallback (FormatCallback cb, uint32_t options, const char* description) +{ + SBTypeSummary retval; + if (cb) + { + retval.SetSP(TypeSummaryImplSP(new CXXFunctionSummaryFormat(options, + [cb] (ValueObject& valobj, Stream& stm, const TypeSummaryOptions& opt) -> bool { + SBStream stream; + SBValue sb_value(valobj.GetSP()); + SBTypeSummaryOptions options(&opt); + if (!cb(sb_value, options, stream)) + return false; + stm.Write(stream.GetData(), stream.GetSize()); + return true; + }, + description ? description : "callback summary formatter"))); + } + + return retval; +} + SBTypeSummary::SBTypeSummary (const lldb::SBTypeSummary &rhs) : m_opaque_sp(rhs.m_opaque_sp) { @@ -167,9 +188,8 @@ SBTypeSummary::IsFunctionCode() { if (!IsValid()) return false; - if (m_opaque_sp->IsScripted()) + if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { - ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get(); const char* ftext = script_summary_ptr->GetPythonScript(); return (ftext && *ftext != 0); } @@ -181,9 +201,8 @@ SBTypeSummary::IsFunctionName() { if (!IsValid()) return false; - if (m_opaque_sp->IsScripted()) + if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { - ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get(); const char* ftext = script_summary_ptr->GetPythonScript(); return (!ftext || *ftext == 0); } @@ -196,10 +215,7 @@ SBTypeSummary::IsSummaryString() if (!IsValid()) return false; - if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback) - return false; - - return !m_opaque_sp->IsScripted(); + return m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eSummaryString; } const char* @@ -207,22 +223,17 @@ SBTypeSummary::GetData () { if (!IsValid()) return NULL; - if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback) - return NULL; - if (m_opaque_sp->IsScripted()) + if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { - ScriptSummaryFormat* script_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get(); const char* fname = script_summary_ptr->GetFunctionName(); const char* ftext = script_summary_ptr->GetPythonScript(); if (ftext && *ftext) return ftext; return fname; } - else - { - StringSummaryFormat* string_summary_ptr = (StringSummaryFormat*)m_opaque_sp.get(); + else if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) return string_summary_ptr->GetSummaryString(); - } + return nullptr; } uint32_t @@ -246,9 +257,10 @@ SBTypeSummary::SetSummaryString (const char* data) { if (!IsValid()) return; - if (m_opaque_sp->IsScripted() || (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback)) + if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(false); - ((StringSummaryFormat*)m_opaque_sp.get())->SetSummaryString(data); + if (StringSummaryFormat* string_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) + string_summary_ptr->SetSummaryString(data); } void @@ -256,9 +268,10 @@ SBTypeSummary::SetFunctionName (const char* data) { if (!IsValid()) return; - if (!m_opaque_sp->IsScripted()) + if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(true); - ((ScriptSummaryFormat*)m_opaque_sp.get())->SetFunctionName(data); + if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) + script_summary_ptr->SetFunctionName(data); } void @@ -266,9 +279,10 @@ SBTypeSummary::SetFunctionCode (const char* data) { if (!IsValid()) return; - if (!m_opaque_sp->IsScripted()) + if (!llvm::isa(m_opaque_sp.get())) ChangeSummaryType(true); - ((ScriptSummaryFormat*)m_opaque_sp.get())->SetPythonScript(data); + if (ScriptSummaryFormat* script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) + script_summary_ptr->SetPythonScript(data); } bool @@ -284,6 +298,15 @@ SBTypeSummary::GetDescription (lldb::SBStream &description, } } +bool +SBTypeSummary::DoesPrintValue (lldb::SBValue value) +{ + if (!IsValid()) + return false; + lldb::ValueObjectSP value_sp = value.GetSP(); + return m_opaque_sp->DoesPrintValue(value_sp.get()); +} + lldb::SBTypeSummary & SBTypeSummary::operator = (const lldb::SBTypeSummary &rhs) { @@ -305,36 +328,44 @@ SBTypeSummary::operator == (lldb::SBTypeSummary &rhs) bool SBTypeSummary::IsEqualTo (lldb::SBTypeSummary &rhs) { - if (IsValid() == false) - return !rhs.IsValid(); - - if (m_opaque_sp->GetType() != rhs.m_opaque_sp->GetType()) - return false; - - if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback) + if (IsValid()) { - lldb_private::CXXFunctionSummaryFormat *self_cxx = (lldb_private::CXXFunctionSummaryFormat*)m_opaque_sp.get(); - lldb_private::CXXFunctionSummaryFormat *other_cxx = (lldb_private::CXXFunctionSummaryFormat*)rhs.m_opaque_sp.get(); - return (self_cxx->m_impl == other_cxx->m_impl); + // valid and invalid are different + if (!rhs.IsValid()) + return false; + } + else + { + // invalid and valid are different + if (rhs.IsValid()) + return false; + else + // both invalid are the same + return true; } - - if (m_opaque_sp->IsScripted() != rhs.m_opaque_sp->IsScripted()) - return false; - - if (IsFunctionCode() != rhs.IsFunctionCode()) - return false; - - if (IsSummaryString() != rhs.IsSummaryString()) - return false; - if (IsFunctionName() != rhs.IsFunctionName()) - return false; - - if ( GetData() == NULL || rhs.GetData() == NULL || strcmp(GetData(), rhs.GetData()) ) + if (m_opaque_sp->GetKind() != rhs.m_opaque_sp->GetKind()) return false; - return GetOptions() == rhs.GetOptions(); + switch (m_opaque_sp->GetKind()) + { + case TypeSummaryImpl::Kind::eCallback: + return llvm::dyn_cast(m_opaque_sp.get()) == llvm::dyn_cast(rhs.m_opaque_sp.get()); + case TypeSummaryImpl::Kind::eScript: + if (IsFunctionCode() != rhs.IsFunctionCode()) + return false; + if (IsFunctionName() != rhs.IsFunctionName()) + return false; + return GetOptions() == rhs.GetOptions(); + case TypeSummaryImpl::Kind::eSummaryString: + if (IsSummaryString() != rhs.IsSummaryString()) + return false; + return GetOptions() == rhs.GetOptions(); + case TypeSummaryImpl::Kind::eInternal: + return (m_opaque_sp.get() == rhs.m_opaque_sp.get()); + } + return false; } bool @@ -373,29 +404,27 @@ SBTypeSummary::CopyOnWrite_Impl() TypeSummaryImplSP new_sp; - if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback) + if (CXXFunctionSummaryFormat* current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { - CXXFunctionSummaryFormat* current_summary_ptr = (CXXFunctionSummaryFormat*)m_opaque_sp.get(); new_sp = TypeSummaryImplSP(new CXXFunctionSummaryFormat(GetOptions(), current_summary_ptr->m_impl, current_summary_ptr->m_description.c_str())); } - else if (m_opaque_sp->IsScripted()) + else if (ScriptSummaryFormat* current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { - ScriptSummaryFormat* current_summary_ptr = (ScriptSummaryFormat*)m_opaque_sp.get(); new_sp = TypeSummaryImplSP(new ScriptSummaryFormat(GetOptions(), current_summary_ptr->GetFunctionName(), current_summary_ptr->GetPythonScript())); } - else { - StringSummaryFormat* current_summary_ptr = (StringSummaryFormat*)m_opaque_sp.get(); + else if (StringSummaryFormat* current_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) + { new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), current_summary_ptr->GetSummaryString())); } - + SetSP(new_sp); - return true; + return nullptr != new_sp.get(); } bool @@ -406,9 +435,9 @@ SBTypeSummary::ChangeSummaryType (bool want_script) TypeSummaryImplSP new_sp; - if (want_script == m_opaque_sp->IsScripted()) + if (want_script == (m_opaque_sp->GetKind() == TypeSummaryImpl::Kind::eScript)) { - if (m_opaque_sp->GetType() == lldb_private::TypeSummaryImpl::eTypeCallback && !want_script) + if (m_opaque_sp->GetKind() == lldb_private::TypeSummaryImpl::Kind::eCallback && !want_script) new_sp = TypeSummaryImplSP(new StringSummaryFormat(GetOptions(), "")); else return CopyOnWrite_Impl(); @@ -426,5 +455,3 @@ SBTypeSummary::ChangeSummaryType (bool want_script) return true; } - -#endif // LLDB_DISABLE_PYTHON diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp index ef62c30e42cf..a8584c5d38c9 100644 --- a/source/API/SBValue.cpp +++ b/source/API/SBValue.cpp @@ -632,7 +632,6 @@ SBValue::GetValueDidChange () return result; } -#ifndef LLDB_DISABLE_PYTHON const char * SBValue::GetSummary () { @@ -681,7 +680,6 @@ SBValue::GetSummary (lldb::SBStream& stream, } return cstr; } -#endif // LLDB_DISABLE_PYTHON const char * SBValue::GetLocation () @@ -753,7 +751,6 @@ SBValue::GetTypeFormat () return format; } -#ifndef LLDB_DISABLE_PYTHON lldb::SBTypeSummary SBValue::GetTypeSummary () { @@ -771,7 +768,6 @@ SBValue::GetTypeSummary () } return summary; } -#endif // LLDB_DISABLE_PYTHON lldb::SBTypeFilter SBValue::GetTypeFilter () @@ -831,7 +827,7 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type) TypeImplSP type_sp (type.GetSP()); if (type.IsValid()) { - sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); + sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetCompilerType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); } } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -856,7 +852,7 @@ SBValue::Cast (SBType type) lldb::ValueObjectSP value_sp(GetSP(locker)); TypeImplSP type_sp (type.GetSP()); if (value_sp && type_sp) - sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue()); + sb_value.SetSP(value_sp->Cast(type_sp->GetCompilerType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue()); return sb_value; } @@ -907,7 +903,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s lldb::TypeImplSP type_impl_sp (sb_type.GetSP()); if (value_sp && type_impl_sp) { - ClangASTType ast_type(type_impl_sp->GetClangASTType(true)); + CompilerType ast_type(type_impl_sp->GetCompilerType(true)); ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); new_value_sp = ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, ast_type); } @@ -936,7 +932,7 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type) if (value_sp) { ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); - new_value_sp = ValueObject::CreateValueObjectFromData(name, **data, exe_ctx, type.GetSP()->GetClangASTType(true)); + new_value_sp = ValueObject::CreateValueObjectFromData(name, **data, exe_ctx, type.GetSP()->GetCompilerType(true)); new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); } sb_value.SetSP(new_value_sp); @@ -1269,6 +1265,12 @@ SBValue::IsRuntimeSupportValue () uint32_t SBValue::GetNumChildren () +{ + return GetNumChildren (UINT32_MAX); +} + +uint32_t +SBValue::GetNumChildren (uint32_t max) { uint32_t num_children = 0; @@ -1276,16 +1278,15 @@ SBValue::GetNumChildren () ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) - num_children = value_sp->GetNumChildren(); + num_children = value_sp->GetNumChildren(max); if (log) - log->Printf ("SBValue(%p)::GetNumChildren () => %u", - static_cast(value_sp.get()), num_children); + log->Printf ("SBValue(%p)::GetNumChildren (%u) => %u", + static_cast(value_sp.get()), max, num_children); return num_children; } - SBValue SBValue::Dereference () { @@ -1306,22 +1307,11 @@ SBValue::Dereference () return sb_value; } +// Deprecated - please use GetType().IsPointerType() instead. bool SBValue::TypeIsPointerType () { - bool is_ptr_type = false; - - ValueLocker locker; - lldb::ValueObjectSP value_sp(GetSP(locker)); - if (value_sp) - is_ptr_type = value_sp->IsPointerType(); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - if (log) - log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", - static_cast(value_sp.get()), is_ptr_type); - - return is_ptr_type; + return GetType().IsPointerType(); } void * @@ -1330,7 +1320,7 @@ SBValue::GetOpaqueType() ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) - return value_sp->GetClangType().GetOpaqueQualType(); + return value_sp->GetCompilerType().GetOpaqueQualType(); return NULL; } @@ -1435,7 +1425,10 @@ lldb::ValueObjectSP SBValue::GetSP (ValueLocker &locker) const { if (!m_opaque_sp || !m_opaque_sp->IsValid()) + { + locker.GetError().SetErrorString("No value"); return ValueObjectSP(); + } return locker.GetLockedSP(*m_opaque_sp.get()); } @@ -1823,7 +1816,7 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error) watch_type |= LLDB_WATCH_TYPE_WRITE; Error rc; - ClangASTType type (value_sp->GetClangType()); + CompilerType type (value_sp->GetCompilerType()); WatchpointSP watchpoint_sp = target_sp->CreateWatchpoint(addr, byte_size, &type, watch_type, rc); error.SetError(rc); diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp index 71fabe0dfc0a..5461b05fb196 100644 --- a/source/API/SBValueList.cpp +++ b/source/API/SBValueList.cpp @@ -39,7 +39,7 @@ public: return *this; m_values = rhs.m_values; return *this; - }; + } uint32_t GetSize () @@ -297,5 +297,3 @@ SBValueList::ref () CreateIfNeeded(); return *m_opaque_ap.get(); } - - diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp index 01ad8157646e..f223357824e8 100644 --- a/source/API/SystemInitializerFull.cpp +++ b/source/API/SystemInitializerFull.cpp @@ -7,18 +7,32 @@ // //===----------------------------------------------------------------------===// +#if !defined(LLDB_DISABLE_PYTHON) +#include "Plugins/ScriptInterpreter/Python/lldb-python.h" +#endif + #include "lldb/API/SystemInitializerFull.h" +#include "lldb/API/SBCommandInterpreter.h" + +#if !defined(LLDB_DISABLE_PYTHON) +#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h" +#endif + #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Initialization/SystemInitializerCommon.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/GoASTContext.h" #include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h" #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" #include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h" #include "Plugins/ABI/SysV-arm/ABISysV_arm.h" #include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h" +#include "Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h" #include "Plugins/ABI/SysV-i386/ABISysV_i386.h" #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" #include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h" @@ -30,14 +44,20 @@ #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" #include "Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h" #include "Plugins/JITLoader/GDB/JITLoaderGDB.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/Go/GoLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h" #include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" +#include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h" #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h" #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h" #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" #include "Plugins/Process/elf-core/ProcessElfCore.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" +#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h" #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" @@ -50,6 +70,10 @@ #include "Plugins/Process/mach-core/ProcessMachCore.h" #include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h" #include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h" +#include "Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h" +#include "Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h" #endif #if defined(__FreeBSD__) @@ -58,11 +82,8 @@ #if defined(_MSC_VER) #include "lldb/Host/windows/windows.h" -#include "Plugins/Process/Windows/ProcessWindows.h" -#endif - -#if !defined(LLDB_DISABLE_PYTHON) -#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "Plugins/Process/Windows/Live/ProcessWindowsLive.h" +#include "Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h" #endif #include "llvm/Support/TargetSelect.h" @@ -74,9 +95,19 @@ using namespace lldb_private; #ifndef LLDB_DISABLE_PYTHON // Defined in the SWIG source file +#if PY_MAJOR_VERSION >= 3 +extern "C" PyObject* +PyInit__lldb(void); + +#define LLDBSwigPyInit PyInit__lldb + +#else extern "C" void init_lldb(void); +#define LLDBSwigPyInit init_lldb +#endif + // these are the Pythonic implementations of the required callbacks // these are scripting-language specific, which is why they belong here // we still need to use function pointers to them instead of relying @@ -124,7 +155,7 @@ LLDBSWIGPythonCallThreadPlan (void *implementor, bool &got_error); extern "C" size_t -LLDBSwigPython_CalculateNumChildren (void *implementor); +LLDBSwigPython_CalculateNumChildren (void *implementor, uint32_t max); extern "C" void * LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); @@ -221,9 +252,17 @@ SystemInitializerFull::~SystemInitializerFull() void SystemInitializerFull::Initialize() { + SystemInitializerCommon::Initialize(); + ScriptInterpreterNone::Initialize(); + +#if !defined(LLDB_DISABLE_PYTHON) InitializeSWIG(); - SystemInitializerCommon::Initialize(); + // ScriptInterpreterPython::Initialize() depends on things like HostInfo being initialized + // so it can compute the python directory etc, so we need to do this after + // SystemInitializerCommon::Initialize(). + ScriptInterpreterPython::Initialize(); +#endif // Initialize LLVM and Clang llvm::InitializeAllTargets(); @@ -231,11 +270,15 @@ SystemInitializerFull::Initialize() llvm::InitializeAllTargetMCs(); llvm::InitializeAllDisassemblers(); + ClangASTContext::Initialize(); + GoASTContext::Initialize(); + ABIMacOSX_i386::Initialize(); ABIMacOSX_arm::Initialize(); ABIMacOSX_arm64::Initialize(); ABISysV_arm::Initialize(); ABISysV_arm64::Initialize(); + ABISysV_hexagon::Initialize(); ABISysV_i386::Initialize(); ABISysV_x86_64::Initialize(); ABISysV_ppc::Initialize(); @@ -246,6 +289,9 @@ SystemInitializerFull::Initialize() JITLoaderGDB::Initialize(); ProcessElfCore::Initialize(); +#if defined(_MSC_VER) + ProcessWinMiniDump::Initialize(); +#endif MemoryHistoryASan::Initialize(); AddressSanitizerRuntime::Initialize(); @@ -261,9 +307,15 @@ SystemInitializerFull::Initialize() AppleObjCRuntimeV1::Initialize(); SystemRuntimeMacOSX::Initialize(); RenderScriptRuntime::Initialize(); + GoLanguageRuntime::Initialize(); + + CPlusPlusLanguage::Initialize(); + GoLanguage::Initialize(); + ObjCLanguage::Initialize(); + ObjCPlusPlusLanguage::Initialize(); #if defined(_MSC_VER) - ProcessWindows::Initialize(); + ProcessWindowsLive::Initialize(); #endif #if defined(__FreeBSD__) ProcessFreeBSD::Initialize(); @@ -272,6 +324,10 @@ SystemInitializerFull::Initialize() SymbolVendorMacOSX::Initialize(); ProcessKDP::Initialize(); ProcessMachCore::Initialize(); + PlatformAppleTVSimulator::Initialize(); + PlatformAppleWatchSimulator::Initialize(); + PlatformRemoteAppleTV::Initialize(); + PlatformRemoteAppleWatch::Initialize(); #endif //---------------------------------------------------------------------- // Platform agnostic plugins @@ -294,7 +350,7 @@ void SystemInitializerFull::InitializeSWIG() { #if !defined(LLDB_DISABLE_PYTHON) ScriptInterpreterPython::InitializeInterpreter( - init_lldb, + LLDBSwigPyInit, LLDBSwigPythonBreakpointCallbackFunction, LLDBSwigPythonWatchpointCallbackFunction, LLDBSwigPythonCallTypeScript, @@ -332,11 +388,16 @@ SystemInitializerFull::Terminate() // Terminate and unload and loaded system or user LLDB plug-ins PluginManager::Terminate(); + + ClangASTContext::Terminate(); + GoASTContext::Terminate(); + ABIMacOSX_i386::Terminate(); ABIMacOSX_arm::Terminate(); ABIMacOSX_arm64::Terminate(); ABISysV_arm::Terminate(); ABISysV_arm64::Terminate(); + ABISysV_hexagon::Terminate(); ABISysV_i386::Terminate(); ABISysV_x86_64::Terminate(); ABISysV_ppc::Terminate(); @@ -347,6 +408,9 @@ SystemInitializerFull::Terminate() JITLoaderGDB::Terminate(); ProcessElfCore::Terminate(); +#if defined(_MSC_VER) + ProcessWinMiniDump::Terminate(); +#endif MemoryHistoryASan::Terminate(); AddressSanitizerRuntime::Terminate(); SymbolVendorELF::Terminate(); @@ -362,10 +426,19 @@ SystemInitializerFull::Terminate() SystemRuntimeMacOSX::Terminate(); RenderScriptRuntime::Terminate(); + CPlusPlusLanguage::Terminate(); + GoLanguage::Terminate(); + ObjCLanguage::Terminate(); + ObjCPlusPlusLanguage::Terminate(); + #if defined(__APPLE__) ProcessMachCore::Terminate(); ProcessKDP::Terminate(); SymbolVendorMacOSX::Terminate(); + PlatformAppleTVSimulator::Terminate(); + PlatformAppleWatchSimulator::Terminate(); + PlatformRemoteAppleTV::Terminate(); + PlatformRemoteAppleWatch::Terminate(); #endif #if defined(__FreeBSD__) @@ -380,8 +453,3 @@ SystemInitializerFull::Terminate() // Now shutdown the common parts, in reverse order. SystemInitializerCommon::Terminate(); } - -void SystemInitializerFull::TerminateSWIG() -{ - -} diff --git a/source/API/liblldb.exports b/source/API/liblldb.exports new file mode 100644 index 000000000000..fd234d11c40c --- /dev/null +++ b/source/API/liblldb.exports @@ -0,0 +1,3 @@ +_ZN4lldb* +_ZNK4lldb* +init_lld* diff --git a/source/API/liblldb.xcode.exports b/source/API/liblldb.xcode.exports new file mode 100644 index 000000000000..9c194fa6ff67 --- /dev/null +++ b/source/API/liblldb.xcode.exports @@ -0,0 +1,3 @@ +__ZN4lldb* +__ZNK4lldb* +_init_lld* diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 23d484f0f68a..54f67b90220a 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes // Other libraries and framework includes -// Project includes +#include "llvm/Support/Casting.h" +// Project includes #include "lldb/Core/Address.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" @@ -31,7 +31,6 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "llvm/Support/Casting.h" using namespace lldb; using namespace lldb_private; @@ -83,9 +82,7 @@ Breakpoint::Breakpoint (Target &new_target, Breakpoint &source_bp) : //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -Breakpoint::~Breakpoint() -{ -} +Breakpoint::~Breakpoint() = default; const lldb::TargetSP Breakpoint::GetTargetSP () @@ -236,7 +233,7 @@ Breakpoint::SetThreadID (lldb::tid_t thread_id) lldb::tid_t Breakpoint::GetThreadID () const { - if (m_options.GetThreadSpecNoCreate() == NULL) + if (m_options.GetThreadSpecNoCreate() == nullptr) return LLDB_INVALID_THREAD_ID; else return m_options.GetThreadSpecNoCreate()->GetTID(); @@ -255,7 +252,7 @@ Breakpoint::SetThreadIndex (uint32_t index) uint32_t Breakpoint::GetThreadIndex() const { - if (m_options.GetThreadSpecNoCreate() == NULL) + if (m_options.GetThreadSpecNoCreate() == nullptr) return 0; else return m_options.GetThreadSpecNoCreate()->GetIndex(); @@ -264,7 +261,7 @@ Breakpoint::GetThreadIndex() const void Breakpoint::SetThreadName (const char *thread_name) { - if (m_options.GetThreadSpec()->GetName() != NULL + if (m_options.GetThreadSpec()->GetName() != nullptr && ::strcmp (m_options.GetThreadSpec()->GetName(), thread_name) == 0) return; @@ -275,8 +272,8 @@ Breakpoint::SetThreadName (const char *thread_name) const char * Breakpoint::GetThreadName () const { - if (m_options.GetThreadSpecNoCreate() == NULL) - return NULL; + if (m_options.GetThreadSpecNoCreate() == nullptr) + return nullptr; else return m_options.GetThreadSpecNoCreate()->GetName(); } @@ -284,7 +281,7 @@ Breakpoint::GetThreadName () const void Breakpoint::SetQueueName (const char *queue_name) { - if (m_options.GetThreadSpec()->GetQueueName() != NULL + if (m_options.GetThreadSpec()->GetQueueName() != nullptr && ::strcmp (m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0) return; @@ -295,8 +292,8 @@ Breakpoint::SetQueueName (const char *queue_name) const char * Breakpoint::GetQueueName () const { - if (m_options.GetThreadSpecNoCreate() == NULL) - return NULL; + if (m_options.GetThreadSpecNoCreate() == nullptr) + return nullptr; else return m_options.GetThreadSpecNoCreate()->GetQueueName(); } @@ -456,7 +453,6 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca if (!seen) new_modules.AppendIfNeeded (module_sp); - } if (new_modules.GetSize() > 0) @@ -474,7 +470,7 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca removed_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved, shared_from_this()); else - removed_locations_event = NULL; + removed_locations_event = nullptr; size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) @@ -502,7 +498,6 @@ Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_loca } if (delete_locations) locations_to_remove.Add (break_loc_sp); - } } @@ -568,7 +563,7 @@ SymbolContextsMightBeEquivalent(SymbolContext &old_sc, SymbolContext &new_sc) } return equivalent_scs; } -} +} // anonymous namespace void Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp) @@ -740,7 +735,7 @@ Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp) locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved, shared_from_this()); else - locations_event = NULL; + locations_event = nullptr; for (BreakpointLocationSP loc_sp : locations_to_remove.BreakpointLocations()) { @@ -804,7 +799,7 @@ Breakpoint::AddName (const char *new_name, Error &error) void Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations) { - assert (s != NULL); + assert (s != nullptr); if (!m_kind_description.empty()) { @@ -849,6 +844,9 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l GetOptions()->GetDescription(s, level); + if (m_precondition_sp) + m_precondition_sp->GetDescription(*s, level); + if (level == lldb::eDescriptionLevelFull) { if (!m_name_list.empty()) @@ -876,7 +874,7 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l { s->Printf ("no locations (pending)."); } - else if (num_locations == 1 && show_locations == false) + else if (num_locations == 1 && !show_locations) { // There is only one location, so we'll just print that location information. GetLocationAtIndex(0)->GetDescription(s, level); @@ -922,7 +920,6 @@ Breakpoint::GetResolverDescription (Stream *s) m_resolver_sp->GetDescription (s); } - bool Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll) { @@ -965,7 +962,7 @@ Breakpoint::BreakpointPrecondition::EvaluatePrecondition(StoppointCallbackContex } void -Breakpoint::BreakpointPrecondition::DescribePrecondition(Stream &stream, lldb::DescriptionLevel level) +Breakpoint::BreakpointPrecondition::GetDescription(Stream &stream, lldb::DescriptionLevel level) { } @@ -993,8 +990,7 @@ Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind) void Breakpoint::SendBreakpointChangedEvent (BreakpointEventData *data) { - - if (data == NULL) + if (data == nullptr) return; if (!m_being_created @@ -1013,9 +1009,7 @@ Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_ty { } -Breakpoint::BreakpointEventData::~BreakpointEventData () -{ -} +Breakpoint::BreakpointEventData::~BreakpointEventData() = default; const ConstString & Breakpoint::BreakpointEventData::GetFlavorString () @@ -1030,7 +1024,6 @@ Breakpoint::BreakpointEventData::GetFlavor () const return BreakpointEventData::GetFlavorString (); } - BreakpointSP & Breakpoint::BreakpointEventData::GetBreakpoint () { @@ -1057,7 +1050,7 @@ Breakpoint::BreakpointEventData::GetEventDataFromEvent (const Event *event) if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString()) return static_cast (event->GetData()); } - return NULL; + return nullptr; } BreakpointEventType @@ -1065,7 +1058,7 @@ Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP { const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get()); - if (data == NULL) + if (data == nullptr) return eBreakpointEventTypeInvalidType; else return data->GetBreakpointEventType(); diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp index 31823886dd9f..81a3dfe50d9b 100644 --- a/source/Breakpoint/BreakpointID.cpp +++ b/source/Breakpoint/BreakpointID.cpp @@ -7,14 +7,12 @@ // //===----------------------------------------------------------------------===// - // C Includes #include // C++ Includes // Other libraries and framework includes // Project includes - #include "lldb/Breakpoint/BreakpointID.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Core/Stream.h" @@ -29,11 +27,9 @@ BreakpointID::BreakpointID (break_id_t bp_id, break_id_t loc_id) : { } -BreakpointID::~BreakpointID () -{ -} +BreakpointID::~BreakpointID() = default; -const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", NULL }; +const char *BreakpointID::g_range_specifiers[] = { "-", "to", "To", "TO", nullptr }; // Tells whether or not STR is valid to use between two strings representing breakpoint IDs, to // indicate a range of breakpoint IDs. This is broken out into a separate function so that we can @@ -43,7 +39,7 @@ bool BreakpointID::IsRangeIdentifier (const char *str) { int specifier_count = 0; - for (int i = 0; g_range_specifiers[i] != NULL; ++i) + for (int i = 0; g_range_specifiers[i] != nullptr; ++i) ++specifier_count; for (int i = 0; i < specifier_count; ++i) @@ -62,10 +58,7 @@ BreakpointID::IsValidIDExpression (const char *str) break_id_t loc_id; BreakpointID::ParseCanonicalReference (str, &bp_id, &loc_id); - if (bp_id == LLDB_INVALID_BREAK_ID) - return false; - else - return true; + return (bp_id != LLDB_INVALID_BREAK_ID); } void @@ -99,7 +92,7 @@ BreakpointID::ParseCanonicalReference (const char *input, break_id_t *break_id_p *break_id_ptr = LLDB_INVALID_BREAK_ID; *break_loc_id_ptr = LLDB_INVALID_BREAK_ID; - if (input == NULL || *input == '\0') + if (input == nullptr || *input == '\0') return false; const char *format = "%i%n.%i%n"; diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp index b8b506750b34..ebf0697c271b 100644 --- a/source/Breakpoint/BreakpointIDList.cpp +++ b/source/Breakpoint/BreakpointIDList.cpp @@ -7,6 +7,10 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/Breakpoint.h" @@ -27,9 +31,7 @@ m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID) { } -BreakpointIDList::~BreakpointIDList () -{ -} +BreakpointIDList::~BreakpointIDList() = default; size_t BreakpointIDList::GetSize() @@ -38,12 +40,9 @@ BreakpointIDList::GetSize() } BreakpointID & -BreakpointIDList::GetBreakpointIDAtIndex (size_t index) +BreakpointIDList::GetBreakpointIDAtIndex(size_t index) { - if (index < m_breakpoint_ids.size()) - return m_breakpoint_ids[index]; - else - return m_invalid_id; + return ((index < m_breakpoint_ids.size()) ? m_breakpoint_ids[index] : m_invalid_id); } bool @@ -124,7 +123,7 @@ BreakpointIDList::FindBreakpointID (const char *bp_id_str, size_t *position) void BreakpointIDList::InsertStringArray (const char **string_array, size_t array_size, CommandReturnObject &result) { - if (string_array == NULL) + if (string_array == nullptr) return; for (uint32_t i = 0; i < array_size; ++i) @@ -385,7 +384,6 @@ BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, } result.SetStatus (eReturnStatusSuccessFinishNoResult); - return; } bool @@ -402,7 +400,7 @@ BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, *range_end_pos = 0; int specifiers_size = 0; - for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i) + for (int i = 0; BreakpointID::g_range_specifiers[i] != nullptr; ++i) ++specifiers_size; for (int i = 0; i < specifiers_size && !is_range_expression; ++i) diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index a199d390803b..5ff91102aadd 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -9,8 +9,6 @@ // C Includes // C++ Includes -#include - // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" @@ -21,9 +19,11 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -88,12 +88,18 @@ BreakpointLocation::GetBreakpoint () return m_owner; } +Target & +BreakpointLocation::GetTarget() +{ + return m_owner.GetTarget(); +} + bool BreakpointLocation::IsEnabled () const { if (!m_owner.IsEnabled()) return false; - else if (m_options_ap.get() != NULL) + else if (m_options_ap.get() != nullptr) return m_options_ap->IsEnabled(); else return true; @@ -123,7 +129,7 @@ BreakpointLocation::SetThreadID (lldb::tid_t thread_id) { // If we're resetting this to an invalid thread id, then // don't make an options pointer just to do that. - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) m_options_ap->SetThreadID (thread_id); } SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); @@ -147,11 +153,10 @@ BreakpointLocation::SetThreadIndex (uint32_t index) { // If we're resetting this to an invalid thread id, then // don't make an options pointer just to do that. - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetIndex(index); } SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); - } uint32_t @@ -166,13 +171,13 @@ BreakpointLocation::GetThreadIndex() const void BreakpointLocation::SetThreadName (const char *thread_name) { - if (thread_name != NULL) + if (thread_name != nullptr) GetLocationOptions()->GetThreadSpec()->SetName(thread_name); else { // If we're resetting this to an invalid thread id, then // don't make an options pointer just to do that. - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetName(thread_name); } SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); @@ -184,19 +189,19 @@ BreakpointLocation::GetThreadName () const if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName(); else - return NULL; + return nullptr; } void BreakpointLocation::SetQueueName (const char *queue_name) { - if (queue_name != NULL) + if (queue_name != nullptr) GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name); else { // If we're resetting this to an invalid thread id, then // don't make an options pointer just to do that. - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) m_options_ap->GetThreadSpec()->SetQueueName(queue_name); } SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged); @@ -208,13 +213,13 @@ BreakpointLocation::GetQueueName () const if (GetOptionsNoCreate()->GetThreadSpecNoCreate()) return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName(); else - return NULL; + return nullptr; } bool BreakpointLocation::InvokeCallback (StoppointCallbackContext *context) { - if (m_options_ap.get() != NULL && m_options_ap->HasCallback()) + if (m_options_ap.get() != nullptr && m_options_ap->HasCallback()) return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID()); else return m_owner.InvokeCallback (context, GetID()); @@ -238,7 +243,6 @@ BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP & SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged); } - void BreakpointLocation::ClearCallback () { @@ -278,11 +282,27 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { - m_user_expression_sp.reset(new ClangUserExpression(condition_text, - NULL, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny)); + LanguageType language = eLanguageTypeUnknown; + // See if we can figure out the language from the frame, otherwise use the default language: + CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); + if (comp_unit) + language = comp_unit->GetLanguage(); + Error error; + m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(condition_text, + nullptr, + language, + Expression::eResultTypeAny, + EvaluateExpressionOptions(), + error)); + if (error.Fail()) + { + if (log) + log->Printf("Error getting condition expression: %s.", error.AsCString()); + m_user_expression_sp.reset(); + return true; + } + StreamString errors; if (!m_user_expression_sp->Parse(errors, @@ -314,7 +334,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) StreamString execution_errors; - ClangExpressionVariableSP result_variable_sp; + ExpressionVariableSP result_variable_sp; ExpressionResults result_code = m_user_expression_sp->Execute(execution_errors, @@ -337,21 +357,20 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) if (result_value_sp) { - Scalar scalar_value; - if (result_value_sp->ResolveValue (scalar_value)) + ret = result_value_sp->IsLogicalTrue(error); + if (log) { - if (scalar_value.ULongLong(1) == 0) - ret = false; - else - ret = true; - if (log) + if (error.Success()) + { log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); - } - else - { - ret = false; - error.SetErrorString("Failed to get an integer result from the expression"); + } + else + { + error.SetErrorString("Failed to get an integer result from the expression"); + ret = false; + } + } } else @@ -385,7 +404,7 @@ BreakpointLocation::SetIgnoreCount (uint32_t n) void BreakpointLocation::DecrementIgnoreCount() { - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) { uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); if (loc_ignore != 0) @@ -396,7 +415,7 @@ BreakpointLocation::DecrementIgnoreCount() bool BreakpointLocation::IgnoreCountShouldStop() { - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) { uint32_t loc_ignore = m_options_ap->GetIgnoreCount(); if (loc_ignore != 0) @@ -413,7 +432,7 @@ BreakpointLocation::IgnoreCountShouldStop() const BreakpointOptions * BreakpointLocation::GetOptionsNoCreate () const { - if (m_options_ap.get() != NULL) + if (m_options_ap.get() != nullptr) return m_options_ap.get(); else return m_owner.GetOptions (); @@ -425,7 +444,7 @@ BreakpointLocation::GetLocationOptions () // If we make the copy we don't copy the callbacks because that is potentially // expensive and we don't want to do that for the simple case where someone is // just disabling the location. - if (m_options_ap.get() == NULL) + if (m_options_ap.get() == nullptr) m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ())); return m_options_ap.get(); @@ -497,7 +516,7 @@ BreakpointLocation::UndoBumpHitCount() bool BreakpointLocation::IsResolved () const { - return m_bp_site_sp.get() != NULL; + return m_bp_site_sp.get() != nullptr; } lldb::BreakpointSiteSP @@ -513,7 +532,7 @@ BreakpointLocation::ResolveBreakpointSite () return true; Process *process = m_owner.GetTarget().GetProcessSP().get(); - if (process == NULL) + if (process == nullptr) return false; lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware()); @@ -601,13 +620,13 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) sc.module_sp->GetFileSpec().Dump (s); } - if (sc.comp_unit != NULL) + if (sc.comp_unit != nullptr) { s->EOL(); s->Indent("compile unit = "); static_cast(sc.comp_unit)->GetFilename().Dump (s); - if (sc.function != NULL) + if (sc.function != nullptr) { s->EOL(); s->Indent("function = "); @@ -648,11 +667,11 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) s->Printf (", "); s->Printf ("address = "); - ExecutionContextScope *exe_scope = NULL; + ExecutionContextScope *exe_scope = nullptr; Target *target = &m_owner.GetTarget(); if (target) exe_scope = target->GetProcessSP().get(); - if (exe_scope == NULL) + if (exe_scope == nullptr) exe_scope = target; if (level == eDescriptionLevelInitial) @@ -710,7 +729,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level) void BreakpointLocation::Dump(Stream *s) const { - if (s == NULL) + if (s == nullptr) return; s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp index 06b270a08ce9..d57cfa68fb80 100644 --- a/source/Breakpoint/BreakpointLocationList.cpp +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes // Other libraries and framework includes @@ -22,7 +21,6 @@ #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" - using namespace lldb; using namespace lldb_private; @@ -32,13 +30,11 @@ BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) : m_address_to_location (), m_mutex (Mutex::eMutexTypeRecursive), m_next_id (0), - m_new_location_recorder (NULL) + m_new_location_recorder (nullptr) { } -BreakpointLocationList::~BreakpointLocationList() -{ -} +BreakpointLocationList::~BreakpointLocationList() = default; BreakpointLocationSP BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols) @@ -163,7 +159,6 @@ BreakpointLocationList::Dump (Stream *s) const s->IndentLess(); } - BreakpointLocationSP BreakpointLocationList::GetByIndex (size_t i) { @@ -285,7 +280,6 @@ BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, Break to_location_sp->ResolveBreakpointSite(); } - bool BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) { @@ -304,7 +298,7 @@ BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc return true; } } - } + } return false; } @@ -348,7 +342,7 @@ void BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) { Mutex::Locker locker (m_mutex); - assert (m_new_location_recorder == NULL); + assert(m_new_location_recorder == nullptr); m_new_location_recorder = &new_locations; } @@ -356,7 +350,7 @@ void BreakpointLocationList::StopRecordingNewLocations () { Mutex::Locker locker (m_mutex); - m_new_location_recorder = NULL; + m_new_location_recorder = nullptr; } void diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp index db76ffb8685c..d2a919756857 100644 --- a/source/Breakpoint/BreakpointOptions.cpp +++ b/source/Breakpoint/BreakpointOptions.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/BreakpointOptions.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/BreakpointOptions.h" + #include "lldb/Core/Stream.h" #include "lldb/Core/StringList.h" #include "lldb/Core/Value.h" @@ -20,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" using namespace lldb; using namespace lldb_private; @@ -59,7 +58,7 @@ BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) : m_ignore_count (rhs.m_ignore_count), m_thread_spec_ap () { - if (rhs.m_thread_spec_ap.get() != NULL) + if (rhs.m_thread_spec_ap.get() != nullptr) m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get())); m_condition_text = rhs.m_condition_text; m_condition_text_hash = rhs.m_condition_text_hash; @@ -77,7 +76,7 @@ BreakpointOptions::operator=(const BreakpointOptions& rhs) m_enabled = rhs.m_enabled; m_one_shot = rhs.m_one_shot; m_ignore_count = rhs.m_ignore_count; - if (rhs.m_thread_spec_ap.get() != NULL) + if (rhs.m_thread_spec_ap.get() != nullptr) m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get())); m_condition_text = rhs.m_condition_text; m_condition_text_hash = rhs.m_condition_text_hash; @@ -102,9 +101,7 @@ BreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig) //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -BreakpointOptions::~BreakpointOptions() -{ -} +BreakpointOptions::~BreakpointOptions() = default; //------------------------------------------------------------------ // Callbacks @@ -144,10 +141,10 @@ BreakpointOptions::InvokeCallback (StoppointCallbackContext *context, { if (m_callback && context->is_synchronous == IsCallbackSynchronous()) { - return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL, - context, - break_id, - break_loc_id); + return m_callback(m_callback_baton_sp ? m_callback_baton_sp->m_data : nullptr, + context, + break_id, + break_loc_id); } else return true; @@ -182,7 +179,7 @@ BreakpointOptions::GetConditionText (size_t *hash) const } else { - return NULL; + return nullptr; } } @@ -195,7 +192,7 @@ BreakpointOptions::GetThreadSpecNoCreate () const ThreadSpec * BreakpointOptions::GetThreadSpec () { - if (m_thread_spec_ap.get() == NULL) + if (m_thread_spec_ap.get() == nullptr) m_thread_spec_ap.reset (new ThreadSpec()); return m_thread_spec_ap.get(); @@ -210,11 +207,10 @@ BreakpointOptions::SetThreadID (lldb::tid_t thread_id) void BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const { - // Figure out if there are any options not at their default value, and only print // anything if there are: - if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ())) + if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification ())) { if (level == lldb::eDescriptionLevelVerbose) { @@ -294,4 +290,3 @@ BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLev s->IndentLess (); s->IndentLess (); } - diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp index 193bc413af05..8a0469a07e46 100644 --- a/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/source/Breakpoint/BreakpointResolverAddress.cpp @@ -16,6 +16,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -26,13 +27,28 @@ using namespace lldb_private; //---------------------------------------------------------------------- // BreakpointResolverAddress: //---------------------------------------------------------------------- +BreakpointResolverAddress::BreakpointResolverAddress +( + Breakpoint *bkpt, + const Address &addr, + const FileSpec &module_spec +) : + BreakpointResolver (bkpt, BreakpointResolver::AddressResolver), + m_addr (addr), + m_resolved_addr(LLDB_INVALID_ADDRESS), + m_module_filespec(module_spec) +{ +} + BreakpointResolverAddress::BreakpointResolverAddress ( Breakpoint *bkpt, const Address &addr ) : BreakpointResolver (bkpt, BreakpointResolver::AddressResolver), - m_addr (addr) + m_addr (addr), + m_resolved_addr(LLDB_INVALID_ADDRESS), + m_module_filespec() { } @@ -44,10 +60,16 @@ BreakpointResolverAddress::~BreakpointResolverAddress () void BreakpointResolverAddress::ResolveBreakpoint (SearchFilter &filter) { - // The address breakpoint only takes once, so if we've already set it we're done. - if (m_breakpoint->GetNumLocations() > 0) - return; - else + // If the address is not section relative, then we should not try to re-resolve it, it is just some + // random address and we wouldn't know what to do on reload. But if it is section relative, we need to + // re-resolve it since the section it's in may have shifted on re-run. + bool re_resolve = false; + if (m_addr.GetSection() || m_module_filespec) + re_resolve = true; + else if (m_breakpoint->GetNumLocations() == 0) + re_resolve = true; + + if (re_resolve) BreakpointResolver::ResolveBreakpoint(filter); } @@ -58,10 +80,14 @@ BreakpointResolverAddress::ResolveBreakpointInModules ModuleList &modules ) { - // The address breakpoint only takes once, so if we've already set it we're done. - if (m_breakpoint->GetNumLocations() > 0) - return; - else + // See comment in ResolveBreakpoint. + bool re_resolve = false; + if (m_addr.GetSection()) + re_resolve = true; + else if (m_breakpoint->GetNumLocations() == 0) + re_resolve = true; + + if (re_resolve) BreakpointResolver::ResolveBreakpointInModules (filter, modules); } @@ -78,14 +104,44 @@ BreakpointResolverAddress::SearchCallback if (filter.AddressPasses (m_addr)) { - BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr)); - if (bp_loc_sp && !m_breakpoint->IsInternal()) + if (m_breakpoint->GetNumLocations() == 0) + { + // If the address is just an offset, and we're given a module, see if we can find the appropriate module + // loaded in the binary, and fix up m_addr to use that. + if (!m_addr.IsSectionOffset() && m_module_filespec) + { + Target &target = m_breakpoint->GetTarget(); + ModuleSpec module_spec(m_module_filespec); + ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec); + if (module_sp) + { + Address tmp_address; + if (module_sp->ResolveFileAddress(m_addr.GetOffset(), tmp_address)) + m_addr = tmp_address; + } + } + + BreakpointLocationSP bp_loc_sp(m_breakpoint->AddLocation(m_addr)); + m_resolved_addr = m_addr.GetLoadAddress(&m_breakpoint->GetTarget()); + if (bp_loc_sp && !m_breakpoint->IsInternal()) + { + StreamString s; + bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("Added location: %s\n", s.GetData()); + } + } + else { - StreamString s; - bp_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf ("Added location: %s\n", s.GetData()); + BreakpointLocationSP loc_sp = m_breakpoint->GetLocationAtIndex(0); + lldb::addr_t cur_load_location = m_addr.GetLoadAddress(&m_breakpoint->GetTarget()); + if (cur_load_location != m_resolved_addr) + { + m_resolved_addr = cur_load_location; + loc_sp->ClearBreakpointSite(); + loc_sp->ResolveBreakpointSite(); + } } } return Searcher::eCallbackReturnStop; @@ -101,7 +157,7 @@ void BreakpointResolverAddress::GetDescription (Stream *s) { s->PutCString ("address = "); - m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); + m_addr.Dump(s, m_breakpoint->GetTarget().GetProcessSP().get(), Address::DumpStyleModuleWithFileAddress, Address::DumpStyleLoadAddress); } void diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp index 581f7b016173..9ae3fe5256d4 100644 --- a/source/Breakpoint/BreakpointResolverName.cpp +++ b/source/Breakpoint/BreakpointResolverName.cpp @@ -7,22 +7,21 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/BreakpointResolverName.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/BreakpointResolverName.h" + #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" using namespace lldb; using namespace lldb_private; @@ -30,15 +29,16 @@ using namespace lldb_private; BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, const char *name_cstr, uint32_t name_type_mask, + LanguageType language, Breakpoint::MatchType type, bool skip_prologue) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_class_name (), m_regex (), m_match_type (type), + m_language (language), m_skip_prologue (skip_prologue) { - if (m_match_type == Breakpoint::Regexp) { if (!m_regex.Compile (name_cstr)) @@ -59,9 +59,11 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, const char *names[], size_t num_names, uint32_t name_type_mask, + LanguageType language, bool skip_prologue) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_match_type (Breakpoint::Exact), + m_language (language), m_skip_prologue (skip_prologue) { for (size_t i = 0; i < num_names; i++) @@ -73,9 +75,11 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, std::vector names, uint32_t name_type_mask, + LanguageType language, bool skip_prologue) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_match_type (Breakpoint::Exact), + m_language (language), m_skip_prologue (skip_prologue) { for (const std::string& name : names) @@ -86,27 +90,27 @@ BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt, RegularExpression &func_regex, + lldb::LanguageType language, bool skip_prologue) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), - m_class_name (NULL), + m_class_name (nullptr), m_regex (func_regex), m_match_type (Breakpoint::Regexp), + m_language (language), m_skip_prologue (skip_prologue) { } -BreakpointResolverName::BreakpointResolverName -( - Breakpoint *bkpt, - const char *class_name, - const char *method, - Breakpoint::MatchType type, - bool skip_prologue -) : +BreakpointResolverName::BreakpointResolverName(Breakpoint *bkpt, + const char *class_name, + const char *method, + Breakpoint::MatchType type, + bool skip_prologue ) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_class_name (class_name), m_regex (), m_match_type (type), + m_language (eLanguageTypeUnknown), m_skip_prologue (skip_prologue) { LookupInfo lookup; @@ -117,9 +121,7 @@ BreakpointResolverName::BreakpointResolverName m_lookups.push_back (lookup); } -BreakpointResolverName::~BreakpointResolverName () -{ -} +BreakpointResolverName::~BreakpointResolverName() = default; BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs) : BreakpointResolver(rhs.m_breakpoint, BreakpointResolver::NameResolver), @@ -127,15 +129,15 @@ BreakpointResolverName::BreakpointResolverName(const BreakpointResolverName &rhs m_class_name(rhs.m_class_name), m_regex(rhs.m_regex), m_match_type (rhs.m_match_type), + m_language (rhs.m_language), m_skip_prologue (rhs.m_skip_prologue) { - } void BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask) { - ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false); + ObjCLanguage::MethodName objc_method(name.GetCString(), false); if (objc_method.IsValid(false)) { std::vector objc_names; @@ -154,12 +156,11 @@ BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_ty { LookupInfo lookup; lookup.name = name; - Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup); + Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, m_language, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup); m_lookups.push_back (lookup); } } - void BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const { @@ -172,7 +173,7 @@ BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t st if (!sc_list.GetContextAtIndex(i, sc)) break; ConstString full_name (sc.GetFunctionName()); - if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL) + if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == nullptr) { sc_list.RemoveContextAtIndex(i); } @@ -184,19 +185,15 @@ BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t st } } - // FIXME: Right now we look at the module level, and call the module's "FindFunctions". // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. Searcher::CallbackReturn -BreakpointResolverName::SearchCallback -( - SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing -) +BreakpointResolverName::SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing) { SymbolContextList func_list; //SymbolContextList sym_list; @@ -204,7 +201,7 @@ BreakpointResolverName::SearchCallback uint32_t i; bool new_location; Address break_addr; - assert (m_breakpoint != NULL); + assert (m_breakpoint != nullptr); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); @@ -215,7 +212,8 @@ BreakpointResolverName::SearchCallback return Searcher::eCallbackReturnStop; } bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; - const bool include_symbols = filter_by_cu == false; + bool filter_by_language = (m_language != eLanguageTypeUnknown); + const bool include_symbols = !filter_by_cu; const bool include_inlines = true; const bool append = true; @@ -227,13 +225,13 @@ BreakpointResolverName::SearchCallback for (const LookupInfo &lookup : m_lookups) { const size_t start_func_idx = func_list.GetSize(); - context.module_sp->FindFunctions (lookup.lookup_name, - NULL, - lookup.name_type_mask, - include_symbols, - include_inlines, - append, - func_list); + context.module_sp->FindFunctions(lookup.lookup_name, + nullptr, + lookup.name_type_mask, + include_symbols, + include_inlines, + append, + func_list); const size_t end_func_idx = func_list.GetSize(); if (start_func_idx < end_func_idx) @@ -258,15 +256,33 @@ BreakpointResolverName::SearchCallback } // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. - if (filter_by_cu) + if (filter_by_cu || filter_by_language) { uint32_t num_functions = func_list.GetSize(); for (size_t idx = 0; idx < num_functions; idx++) { + bool remove_it = false; SymbolContext sc; func_list.GetContextAtIndex(idx, sc); - if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) + if (filter_by_cu) + { + if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) + remove_it = true; + } + + if (filter_by_language) + { + LanguageType sym_language = sc.GetLanguage(); + if ((Language::GetPrimaryLanguage(sym_language) != + Language::GetPrimaryLanguage(m_language)) && + (sym_language != eLanguageTypeUnknown)) + { + remove_it = true; + } + } + + if (remove_it) { func_list.RemoveContextAtIndex(idx); num_functions--; @@ -374,12 +390,15 @@ BreakpointResolverName::GetDescription (Stream *s) s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString()); } } + if (m_language != eLanguageTypeUnknown) + { + s->Printf (", language = %s", Language::GetNameForLanguageType(m_language)); + } } void BreakpointResolverName::Dump (Stream *s) const { - } lldb::BreakpointResolverSP diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp index e9ce812e7732..d2aaea098cdb 100644 --- a/source/Breakpoint/BreakpointSite.cpp +++ b/source/Breakpoint/BreakpointSite.cpp @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/BreakpointSite.h" - // C Includes // C++ Includes #include // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/BreakpointSite.h" + #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSiteList.h" @@ -23,13 +23,10 @@ using namespace lldb; using namespace lldb_private; -BreakpointSite::BreakpointSite -( - BreakpointSiteList *list, - const BreakpointLocationSP& owner, - lldb::addr_t addr, - bool use_hardware -) : +BreakpointSite::BreakpointSite(BreakpointSiteList *list, + const BreakpointLocationSP& owner, + lldb::addr_t addr, + bool use_hardware) : StoppointLocation(GetNextID(), addr, 0, use_hardware), m_type (eSoftware), // Process subclasses need to set this correctly using SetType() m_saved_opcode(), @@ -85,7 +82,7 @@ BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) void BreakpointSite::Dump(Stream *s) const { - if (s == NULL) + if (s == nullptr) return; s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u", @@ -205,6 +202,7 @@ BreakpointSite::ValidForThisThread (Thread *thread) void BreakpointSite::BumpHitCounts() { + Mutex::Locker locker(m_owners_mutex); for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) { loc_sp->BumpHitCount(); @@ -253,3 +251,14 @@ BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *in } return false; } + +size_t +BreakpointSite::CopyOwnersList (BreakpointLocationCollection &out_collection) +{ + Mutex::Locker locker(m_owners_mutex); + for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) + { + out_collection.Add(loc_sp); + } + return out_collection.GetSize(); +} diff --git a/source/Breakpoint/StoppointCallbackContext.cpp b/source/Breakpoint/StoppointCallbackContext.cpp index 2266c3e429c6..9932843714f8 100644 --- a/source/Breakpoint/StoppointCallbackContext.cpp +++ b/source/Breakpoint/StoppointCallbackContext.cpp @@ -7,17 +7,16 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/StoppointCallbackContext.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/StoppointCallbackContext.h" using namespace lldb_private; StoppointCallbackContext::StoppointCallbackContext() : - event (NULL), + event (nullptr), exe_ctx_ref (), is_synchronous (false) { @@ -33,7 +32,7 @@ StoppointCallbackContext::StoppointCallbackContext(Event *e, const ExecutionCont void StoppointCallbackContext::Clear() { - event = NULL; + event = nullptr; exe_ctx_ref.Clear(); is_synchronous = false; } diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp index 45559b1901ad..00a328e3039f 100644 --- a/source/Breakpoint/Watchpoint.cpp +++ b/source/Breakpoint/Watchpoint.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/Watchpoint.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/Watchpoint.h" + #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Value.h" @@ -22,12 +22,12 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" using namespace lldb; using namespace lldb_private; -Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware) : +Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const CompilerType *type, bool hardware) : StoppointLocation (0, addr, size, hardware), m_target(target), m_enabled(false), @@ -67,9 +67,7 @@ Watchpoint::Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const m_being_created = false; } -Watchpoint::~Watchpoint() -{ -} +Watchpoint::~Watchpoint() = default; // This function is used when "baton" doesn't need to be freed void @@ -102,7 +100,6 @@ void Watchpoint::SetDeclInfo (const std::string &str) { m_decl_str = str; - return; } std::string @@ -115,7 +112,6 @@ void Watchpoint::SetWatchSpec (const std::string &str) { m_watch_spec_str = str; - return; } // Override default impl of StoppointLocation::IsHardware() since m_is_hardware @@ -154,10 +150,7 @@ Watchpoint::CaptureWatchedValue (const ExecutionContext &exe_ctx) } m_new_value_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), watch_name.AsCString(), watch_address, m_type); m_new_value_sp = m_new_value_sp->CreateConstantValue(watch_name); - if (m_new_value_sp && m_new_value_sp->GetError().Success()) - return true; - else - return false; + return (m_new_value_sp && m_new_value_sp->GetError().Success()); } void @@ -190,9 +183,6 @@ Watchpoint::ShouldStop (StoppointCallbackContext *context) if (!IsEnabled()) return false; - if (GetHitCount() <= GetIgnoreCount()) - return false; - return true; } @@ -200,7 +190,6 @@ void Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level) { DumpWithLevel(s, level); - return; } void @@ -209,7 +198,7 @@ Watchpoint::Dump(Stream *s) const DumpWithLevel(s, lldb::eDescriptionLevelBrief); } -// If prefix is NULL, we display the watch id and ignore the prefix altogether. +// If prefix is nullptr, we display the watch id and ignore the prefix altogether. void Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const { @@ -218,21 +207,38 @@ Watchpoint::DumpSnapshots(Stream *s, const char *prefix) const s->Printf("\nWatchpoint %u hit:", GetID()); prefix = ""; } - + if (m_old_value_sp) { - s->Printf("\n%sold value: %s", prefix, m_old_value_sp->GetValueAsCString()); + const char *old_value_cstr = m_old_value_sp->GetValueAsCString(); + if (old_value_cstr && old_value_cstr[0]) + s->Printf("\n%sold value: %s", prefix, old_value_cstr); + else + { + const char *old_summary_cstr = m_old_value_sp-> GetSummaryAsCString(); + if (old_summary_cstr && old_summary_cstr[0]) + s->Printf("\n%sold value: %s", prefix, old_summary_cstr); + } } + if (m_new_value_sp) { - s->Printf("\n%snew value: %s", prefix, m_new_value_sp->GetValueAsCString()); + const char *new_value_cstr = m_new_value_sp->GetValueAsCString(); + if (new_value_cstr && new_value_cstr[0]) + s->Printf("\n%snew value: %s", prefix, new_value_cstr); + else + { + const char *new_summary_cstr = m_new_value_sp-> GetSummaryAsCString(); + if (new_summary_cstr && new_summary_cstr[0]) + s->Printf("\n%snew value: %s", prefix, new_summary_cstr); + } } } void Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const { - if (s == NULL) + if (s == nullptr) return; assert(description_level >= lldb::eDescriptionLevelBrief && @@ -334,11 +340,13 @@ Watchpoint::WatchpointRead () const { return m_watch_read != 0; } + bool Watchpoint::WatchpointWrite () const { return m_watch_write != 0; } + uint32_t Watchpoint::GetIgnoreCount () const { @@ -363,15 +371,26 @@ Watchpoint::InvokeCallback (StoppointCallbackContext *context) void Watchpoint::SetCondition (const char *condition) { - if (condition == NULL || condition[0] == '\0') + if (condition == nullptr || condition[0] == '\0') { if (m_condition_ap.get()) m_condition_ap.reset(); } else { - // Pass NULL for expr_prefix (no translation-unit level definitions). - m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); + // Pass nullptr for expr_prefix (no translation-unit level definitions). + Error error; + m_condition_ap.reset(m_target.GetUserExpressionForLanguage(condition, + nullptr, + lldb::eLanguageTypeUnknown, + UserExpression::eResultTypeAny, + EvaluateExpressionOptions(), + error)); + if (error.Fail()) + { + // FIXME: Log something... + m_condition_ap.reset(); + } } SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged); } @@ -382,7 +401,7 @@ Watchpoint::GetConditionText () const if (m_condition_ap.get()) return m_condition_ap->GetUserText(); else - return NULL; + return nullptr; } void @@ -399,8 +418,7 @@ Watchpoint::SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind) void Watchpoint::SendWatchpointChangedEvent (WatchpointEventData *data) { - - if (data == NULL) + if (data == nullptr) return; if (!m_being_created @@ -418,9 +436,7 @@ Watchpoint::WatchpointEventData::WatchpointEventData (WatchpointEventType sub_ty { } -Watchpoint::WatchpointEventData::~WatchpointEventData () -{ -} +Watchpoint::WatchpointEventData::~WatchpointEventData() = default; const ConstString & Watchpoint::WatchpointEventData::GetFlavorString () @@ -435,7 +451,6 @@ Watchpoint::WatchpointEventData::GetFlavor () const return WatchpointEventData::GetFlavorString (); } - WatchpointSP & Watchpoint::WatchpointEventData::GetWatchpoint () { @@ -462,7 +477,7 @@ Watchpoint::WatchpointEventData::GetEventDataFromEvent (const Event *event) if (event_data && event_data->GetFlavor() == WatchpointEventData::GetFlavorString()) return static_cast (event->GetData()); } - return NULL; + return nullptr; } WatchpointEventType @@ -470,7 +485,7 @@ Watchpoint::WatchpointEventData::GetWatchpointEventTypeFromEvent (const EventSP { const WatchpointEventData *data = GetEventDataFromEvent (event_sp.get()); - if (data == NULL) + if (data == nullptr) return eWatchpointEventTypeInvalidType; else return data->GetWatchpointEventType(); diff --git a/source/Breakpoint/WatchpointList.cpp b/source/Breakpoint/WatchpointList.cpp index 472bae06b441..64bf5cd63ed0 100644 --- a/source/Breakpoint/WatchpointList.cpp +++ b/source/Breakpoint/WatchpointList.cpp @@ -75,10 +75,15 @@ WatchpointList::FindByAddress (lldb::addr_t addr) const { wp_collection::const_iterator pos, end = m_watchpoints.end(); for (pos = m_watchpoints.begin(); pos != end; ++pos) - if ((*pos)->GetLoadAddress() == addr) { + { + lldb::addr_t wp_addr = (*pos)->GetLoadAddress(); + uint32_t wp_bytesize = (*pos)->GetByteSize(); + if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr)) + { wp_sp = *pos; break; } + } } return wp_sp; diff --git a/source/Breakpoint/WatchpointOptions.cpp b/source/Breakpoint/WatchpointOptions.cpp index c2c9696c4ce7..365d884691ef 100644 --- a/source/Breakpoint/WatchpointOptions.cpp +++ b/source/Breakpoint/WatchpointOptions.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Breakpoint/WatchpointOptions.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Breakpoint/WatchpointOptions.h" + #include "lldb/Core/Stream.h" #include "lldb/Core/StringList.h" #include "lldb/Core/Value.h" @@ -20,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" using namespace lldb; using namespace lldb_private; @@ -51,7 +50,7 @@ WatchpointOptions::WatchpointOptions(const WatchpointOptions& rhs) : m_callback_is_synchronous (rhs.m_callback_is_synchronous), m_thread_spec_ap () { - if (rhs.m_thread_spec_ap.get() != NULL) + if (rhs.m_thread_spec_ap.get() != nullptr) m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get())); } @@ -64,7 +63,7 @@ WatchpointOptions::operator=(const WatchpointOptions& rhs) m_callback = rhs.m_callback; m_callback_baton_sp = rhs.m_callback_baton_sp; m_callback_is_synchronous = rhs.m_callback_is_synchronous; - if (rhs.m_thread_spec_ap.get() != NULL) + if (rhs.m_thread_spec_ap.get() != nullptr) m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get())); return *this; } @@ -87,9 +86,7 @@ WatchpointOptions::CopyOptionsNoCallback (WatchpointOptions &orig) //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -WatchpointOptions::~WatchpointOptions() -{ -} +WatchpointOptions::~WatchpointOptions() = default; //------------------------------------------------------------------ // Callbacks @@ -128,9 +125,9 @@ WatchpointOptions::InvokeCallback (StoppointCallbackContext *context, { if (m_callback && context->is_synchronous == IsCallbackSynchronous()) { - return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL, - context, - watch_id); + return m_callback(m_callback_baton_sp ? m_callback_baton_sp->m_data : nullptr, + context, + watch_id); } else return true; @@ -151,7 +148,7 @@ WatchpointOptions::GetThreadSpecNoCreate () const ThreadSpec * WatchpointOptions::GetThreadSpec () { - if (m_thread_spec_ap.get() == NULL) + if (m_thread_spec_ap.get() == nullptr) m_thread_spec_ap.reset (new ThreadSpec()); return m_thread_spec_ap.get(); @@ -172,14 +169,14 @@ WatchpointOptions::GetCallbackDescription (Stream *s, lldb::DescriptionLevel lev m_callback_baton_sp->GetDescription (s, level); } } + void WatchpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const { - // Figure out if there are any options not at their default value, and only print // anything if there are: - if ((GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ())) + if ((GetThreadSpecNoCreate() != nullptr && GetThreadSpecNoCreate()->HasSpecification ())) { if (level == lldb::eDescriptionLevelVerbose) { @@ -238,4 +235,3 @@ WatchpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLev s->IndentLess (); s->IndentLess (); } - diff --git a/source/Commands/CommandObjectApropos.h b/source/Commands/CommandObjectApropos.h index f5154177bb29..d04620bc5f2d 100644 --- a/source/Commands/CommandObjectApropos.h +++ b/source/Commands/CommandObjectApropos.h @@ -28,17 +28,14 @@ public: CommandObjectApropos (CommandInterpreter &interpreter); - virtual - ~CommandObjectApropos (); + ~CommandObjectApropos() override; protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result); - - + bool + DoExecute(Args& command, + CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectApropos_h_ +#endif // liblldb_CommandObjectApropos_h_ diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp index cf32d104911c..9f22bba78c55 100644 --- a/source/Commands/CommandObjectArgs.cpp +++ b/source/Commands/CommandObjectArgs.cpp @@ -17,9 +17,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangFunction.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -148,8 +146,14 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) result.SetStatus (eReturnStatusFailed); return false; } - - ClangASTContext &ast_context = thread_module_sp->GetClangASTContext(); + + TypeSystem *type_system = thread_module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system == nullptr) + { + result.AppendError ("Unable to create C type system."); + result.SetStatus (eReturnStatusFailed); + return false; + } ValueList value_list; @@ -158,7 +162,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) const char *arg_type_cstr = args.GetArgumentAtIndex(arg_index); Value value; value.SetValueType(Value::eValueTypeScalar); - ClangASTType clang_type; + CompilerType compiler_type; char *int_pos; if ((int_pos = strstr (const_cast(arg_type_cstr), "int"))) @@ -200,10 +204,9 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) result.SetStatus (eReturnStatusFailed); return false; } + compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize(encoding, width); - clang_type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width); - - if (!clang_type.IsValid()) + if (!compiler_type.IsValid()) { result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n", arg_type_cstr, @@ -217,9 +220,9 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) else if (strchr (arg_type_cstr, '*')) { if (!strcmp (arg_type_cstr, "void*")) - clang_type = ast_context.GetBasicType(eBasicTypeVoid).GetPointerType(); + compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); else if (!strcmp (arg_type_cstr, "char*")) - clang_type = ast_context.GetCStringType (false); + compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeChar).GetPointerType(); else { result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr); @@ -234,7 +237,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) return false; } - value.SetClangType (clang_type); + value.SetCompilerType (compiler_type); value_list.PushValue(value); } diff --git a/source/Commands/CommandObjectArgs.h b/source/Commands/CommandObjectArgs.h index 6691283ce099..4a4e1c35cf31 100644 --- a/source/Commands/CommandObjectArgs.h +++ b/source/Commands/CommandObjectArgs.h @@ -16,7 +16,6 @@ // Project includes #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Core/Language.h" namespace lldb_private { @@ -30,17 +29,16 @@ namespace lldb_private { CommandOptions (CommandInterpreter &interpreter); - virtual - ~CommandOptions (); + ~CommandOptions() override; - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg); + Error + SetOptionValue(uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting (); + OptionParsingStarting() override; const OptionDefinition* - GetDefinitions (); + GetDefinitions() override; // Options table: Required for subclasses of Options. @@ -49,24 +47,20 @@ namespace lldb_private { CommandObjectArgs (CommandInterpreter &interpreter); - virtual - ~CommandObjectArgs (); + ~CommandObjectArgs() override; - virtual Options * - GetOptions (); - + GetOptions() override; protected: CommandOptions m_options; - virtual bool - DoExecute ( Args& command, - CommandReturnObject &result); - + bool + DoExecute(Args& command, + CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectArgs_h_ +#endif // liblldb_CommandObjectArgs_h_ diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index 162bfb4b5a76..bb59e1f82e8d 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -26,7 +26,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Target.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Target/StackFrame.h" @@ -77,11 +77,10 @@ public: } - virtual - ~CommandObjectBreakpointSet () {} + ~CommandObjectBreakpointSet () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -111,6 +110,7 @@ public: m_throw_bp (true), m_hardware (false), m_exception_language (eLanguageTypeUnknown), + m_language (lldb::eLanguageTypeUnknown), m_skip_prologue (eLazyBoolCalculate), m_one_shot (false), m_all_files (false), @@ -119,11 +119,10 @@ public: } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -164,7 +163,7 @@ public: case 'E': { - LanguageType language = LanguageRuntime::GetLanguageTypeFromString (option_arg); + LanguageType language = Language::GetLanguageTypeFromString (option_arg); switch (language) { @@ -249,6 +248,12 @@ public: break; } + case 'L': + m_language = Language::GetLanguageTypeFromString (option_arg); + if (m_language == eLanguageTypeUnknown) + error.SetErrorStringWithFormat ("Unknown language type: '%s' for breakpoint", option_arg); + break; + case 'm': { bool success; @@ -349,7 +354,7 @@ public: return error; } void - OptionParsingStarting () + OptionParsingStarting () override { m_condition.clear(); m_filenames.Clear(); @@ -370,6 +375,7 @@ public: m_throw_bp = true; m_hardware = false; m_exception_language = eLanguageTypeUnknown; + m_language = lldb::eLanguageTypeUnknown; m_skip_prologue = eLazyBoolCalculate; m_one_shot = false; m_use_dummy = false; @@ -380,7 +386,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -411,6 +417,7 @@ public: bool m_throw_bp; bool m_hardware; // Request to use hardware breakpoints lldb::LanguageType m_exception_language; + lldb::LanguageType m_language; LazyBool m_skip_prologue; bool m_one_shot; bool m_use_dummy; @@ -421,9 +428,9 @@ public: }; protected: - virtual bool + bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); @@ -500,11 +507,32 @@ protected: break; case eSetTypeAddress: // Breakpoint by address - bp = target->CreateBreakpoint (m_options.m_load_addr, - internal, - m_options.m_hardware).get(); + { + // If a shared library has been specified, make an lldb_private::Address with the library, and + // use that. That way the address breakpoint will track the load location of the library. + size_t num_modules_specified = m_options.m_modules.GetSize(); + if (num_modules_specified == 1) + { + const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); + bp = target->CreateAddressInModuleBreakpoint (m_options.m_load_addr, + internal, + file_spec, + m_options.m_hardware).get(); + } + else if (num_modules_specified == 0) + { + bp = target->CreateBreakpoint (m_options.m_load_addr, + internal, + m_options.m_hardware).get(); + } + else + { + result.AppendError("Only one shared library can be specified for address breakpoints."); + result.SetStatus(eReturnStatusFailed); + return false; + } break; - + } case eSetTypeFunctionName: // Breakpoint by function name { uint32_t name_type_mask = m_options.m_func_name_type_mask; @@ -516,6 +544,7 @@ protected: &(m_options.m_filenames), m_options.m_func_names, name_type_mask, + m_options.m_language, m_options.m_skip_prologue, internal, m_options.m_hardware).get(); @@ -538,6 +567,7 @@ protected: bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp, + m_options.m_language, m_options.m_skip_prologue, internal, m_options.m_hardware).get(); @@ -709,6 +739,7 @@ private: #define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 ) #define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) #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) ) OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = @@ -756,14 +787,21 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = // "Set the breakpoint by source location at this particular column."}, { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeAddressOrExpression, - "Set the breakpoint by address, at the specified address."}, + "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 - with the -s option - then the address will be treated as " + "a file address in that module, and resolved accordingly. Again, this will allow lldb to track 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, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" }, { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and " - "for Objective C this means a full function prototype with class and selector. " + "for Objective C this means a full function prototype with class and selector. " "Can be repeated multiple times to make one breakpoint for multiple names." }, { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeSelector, @@ -800,6 +838,9 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, NULL, NULL, 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, NULL, NULL, 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, NULL, NULL, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." }, @@ -840,11 +881,10 @@ public: } - virtual - ~CommandObjectBreakpointModify () {} + ~CommandObjectBreakpointModify () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -874,11 +914,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -979,7 +1018,7 @@ public: return error; } void - OptionParsingStarting () + OptionParsingStarting () override { m_ignore_count = 0; m_thread_id = LLDB_INVALID_THREAD_ID; @@ -999,7 +1038,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1031,8 +1070,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); if (target == NULL) @@ -1159,12 +1198,11 @@ public: } - virtual - ~CommandObjectBreakpointEnable () {} + ~CommandObjectBreakpointEnable () override {} protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (target == NULL) @@ -1279,12 +1317,11 @@ the second re-enables the first location." } - virtual - ~CommandObjectBreakpointDisable () {} + ~CommandObjectBreakpointDisable () override {} protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (target == NULL) @@ -1389,11 +1426,10 @@ public: } - virtual - ~CommandObjectBreakpointList () {} + ~CommandObjectBreakpointList () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1409,11 +1445,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1444,7 +1479,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_level = lldb::eDescriptionLevelFull; m_internal = false; @@ -1452,7 +1487,7 @@ public: } const OptionDefinition * - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1470,8 +1505,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); @@ -1586,11 +1621,10 @@ public: { } - virtual - ~CommandObjectBreakpointClear () {} + ~CommandObjectBreakpointClear () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1606,11 +1640,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1634,14 +1667,14 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_filename.clear(); m_line_num = 0; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1658,8 +1691,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (target == NULL) @@ -1786,11 +1819,10 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectBreakpointDelete () {} + ~CommandObjectBreakpointDelete () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1806,11 +1838,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1834,14 +1865,14 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_use_dummy = false; m_force = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1856,8 +1887,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); @@ -1976,27 +2007,26 @@ public: } - virtual - ~BreakpointNameOptionGroup () + ~BreakpointNameOptionGroup () override { } - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions () override { return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition); } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_breakpoint_name_options; } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_value) + const char *option_value) override { Error error; const int short_option = g_breakpoint_name_options[option_idx].short_option; @@ -2024,8 +2054,8 @@ public: return error; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { m_name.Clear(); m_breakpoint.Clear(); @@ -2062,18 +2092,17 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectBreakpointNameAdd () {} + ~CommandObjectBreakpointNameAdd () override {} Options * - GetOptions () + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { if (!m_name_options.m_name.OptionWasSet()) { @@ -2158,18 +2187,17 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectBreakpointNameDelete () {} + ~CommandObjectBreakpointNameDelete () override {} Options * - GetOptions () + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { if (!m_name_options.m_name.OptionWasSet()) { @@ -2243,18 +2271,17 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectBreakpointNameList () {} + ~CommandObjectBreakpointNameList () override {} Options * - GetOptions () + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); @@ -2339,8 +2366,7 @@ public: } - virtual - ~CommandObjectBreakpointName () + ~CommandObjectBreakpointName () override { } diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h index 3fdd2a5f56be..123e8232c987 100644 --- a/source/Commands/CommandObjectBreakpoint.h +++ b/source/Commands/CommandObjectBreakpoint.h @@ -34,8 +34,7 @@ class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword public: CommandObjectMultiwordBreakpoint (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordBreakpoint (); + ~CommandObjectMultiwordBreakpoint() override; static void VerifyBreakpointOrLocationIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids) @@ -56,4 +55,4 @@ private: } // namespace lldb_private -#endif // liblldb_CommandObjectBreakpoint_h_ +#endif // liblldb_CommandObjectBreakpoint_h_ diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index ac9c9a64188c..7b58bf9185bc 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -178,17 +178,16 @@ are no syntax errors may indicate that a function was declared but never called. m_arguments.push_back (arg); } - virtual - ~CommandObjectBreakpointCommandAdd () {} + ~CommandObjectBreakpointCommandAdd () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -199,8 +198,8 @@ are no syntax errors may indicate that a function was declared but never called. } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override { io_handler.SetIsDone(true); @@ -315,11 +314,10 @@ are no syntax errors may indicate that a function was declared but never called. { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -374,7 +372,7 @@ are no syntax errors may indicate that a function was declared but never called. return error; } void - OptionParsingStarting () + OptionParsingStarting () override { m_use_commands = true; m_use_script_language = false; @@ -388,7 +386,7 @@ are no syntax errors may indicate that a function was declared but never called. } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -412,8 +410,8 @@ are no syntax errors may indicate that a function was declared but never called. }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); @@ -596,11 +594,10 @@ public: } - virtual - ~CommandObjectBreakpointCommandDelete () {} + ~CommandObjectBreakpointCommandDelete () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -615,11 +612,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -639,13 +635,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_use_dummy = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -659,8 +655,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); @@ -764,13 +760,12 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectBreakpointCommandList () {} + ~CommandObjectBreakpointCommandList () override {} protected: - virtual bool + bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); diff --git a/source/Commands/CommandObjectBreakpointCommand.h b/source/Commands/CommandObjectBreakpointCommand.h index e91790779510..94afc785c575 100644 --- a/source/Commands/CommandObjectBreakpointCommand.h +++ b/source/Commands/CommandObjectBreakpointCommand.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes - // Other libraries and framework includes // Project includes @@ -23,7 +22,6 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" - namespace lldb_private { //------------------------------------------------------------------------- @@ -35,11 +33,9 @@ class CommandObjectBreakpointCommand : public CommandObjectMultiword public: CommandObjectBreakpointCommand (CommandInterpreter &interpreter); - virtual - ~CommandObjectBreakpointCommand (); - + ~CommandObjectBreakpointCommand() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectBreakpointCommand_h_ +#endif // liblldb_CommandObjectBreakpointCommand_h_ diff --git a/source/Commands/CommandObjectBugreport.cpp b/source/Commands/CommandObjectBugreport.cpp index f171d2f6267f..3d00cb817e3d 100644 --- a/source/Commands/CommandObjectBugreport.cpp +++ b/source/Commands/CommandObjectBugreport.cpp @@ -43,7 +43,7 @@ public: m_option_group.Finalize(); } - ~CommandObjectBugreportUnwind() + ~CommandObjectBugreportUnwind() override { } diff --git a/source/Commands/CommandObjectBugreport.h b/source/Commands/CommandObjectBugreport.h index d062e0d79373..3adde51e0274 100644 --- a/source/Commands/CommandObjectBugreport.h +++ b/source/Commands/CommandObjectBugreport.h @@ -27,10 +27,9 @@ class CommandObjectMultiwordBugreport : public CommandObjectMultiword public: CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordBugreport(); + ~CommandObjectMultiwordBugreport() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectBugreport_h_ +#endif // liblldb_CommandObjectBugreport_h_ diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index f56d089877de..e859b5d64b11 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -47,10 +47,10 @@ public: { } - ~CommandObjectCommandsHistory () {} + ~CommandObjectCommandsHistory () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -70,11 +70,10 @@ protected: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -109,7 +108,7 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_start_idx.Clear(); m_stop_idx.Clear(); @@ -118,7 +117,7 @@ protected: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -136,7 +135,7 @@ protected: }; bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet()) { @@ -259,15 +258,15 @@ public: m_arguments.push_back (arg); } - ~CommandObjectCommandsSource () {} + ~CommandObjectCommandsSource () override {} - virtual const char* - GetRepeatCommand (Args ¤t_command_args, uint32_t index) + const char* + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override { return ""; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -275,7 +274,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -291,8 +290,8 @@ public: return matches.GetSize(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -311,11 +310,10 @@ protected: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -343,7 +341,7 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_stop_on_error.Clear(); m_silent_run.Clear(); @@ -351,7 +349,7 @@ protected: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -368,7 +366,7 @@ protected: }; bool - DoExecute(Args& command, CommandReturnObject &result) + DoExecute(Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 1) @@ -553,13 +551,13 @@ rather than using a positional placeholder:" R"( m_arguments.push_back (arg3); } - ~CommandObjectCommandsAlias () + ~CommandObjectCommandsAlias () override { } protected: - virtual bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) + bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) override { Args args (raw_command_line); std::string raw_command_string (raw_command_line); @@ -820,13 +818,13 @@ public: m_arguments.push_back (arg); } - ~CommandObjectCommandsUnalias() + ~CommandObjectCommandsUnalias() override { } protected: bool - DoExecute (Args& args, CommandReturnObject &result) + DoExecute (Args& args, CommandReturnObject &result) override { CommandObject::CommandMap::iterator pos; CommandObject *cmd_obj; @@ -913,13 +911,13 @@ public: m_arguments.push_back (arg); } - ~CommandObjectCommandsDelete() + ~CommandObjectCommandsDelete() override { } protected: bool - DoExecute (Args& args, CommandReturnObject &result) + DoExecute (Args& args, CommandReturnObject &result) override { CommandObject::CommandMap::iterator pos; @@ -1000,7 +998,7 @@ a number follows 'f':" R"( ); } - ~CommandObjectCommandsAddRegex() + ~CommandObjectCommandsAddRegex() override { } @@ -1250,11 +1248,10 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1277,14 +1274,14 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { m_help.clear(); m_syntax.clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1363,13 +1360,12 @@ public: } } - virtual - ~CommandObjectPythonFunction () + ~CommandObjectPythonFunction () override { } - virtual bool - IsRemovable () const + bool + IsRemovable () const override { return true; } @@ -1386,8 +1382,8 @@ public: return m_synchro; } - virtual const char * - GetHelpLong () + const char * + GetHelpLong () override { if (!m_fetched_help_long) { @@ -1404,8 +1400,8 @@ public: } protected: - virtual bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) + bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) override { ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); @@ -1470,13 +1466,12 @@ public: GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); } - virtual - ~CommandObjectScriptingObject () + ~CommandObjectScriptingObject () override { } - virtual bool - IsRemovable () const + bool + IsRemovable () const override { return true; } @@ -1493,8 +1488,8 @@ public: return m_synchro; } - virtual const char * - GetHelp () + const char * + GetHelp () override { if (!m_fetched_help_short) { @@ -1510,8 +1505,8 @@ public: return CommandObjectRaw::GetHelp(); } - virtual const char * - GetHelpLong () + const char * + GetHelpLong () override { if (!m_fetched_help_long) { @@ -1528,8 +1523,8 @@ public: } protected: - virtual bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) + bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) override { ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); @@ -1592,11 +1587,11 @@ public: m_arguments.push_back (arg1); } - ~CommandObjectCommandsScriptImport () + ~CommandObjectCommandsScriptImport () override { } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -1604,7 +1599,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -1620,8 +1615,8 @@ public: return matches.GetSize(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1637,11 +1632,10 @@ protected: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1660,13 +1654,13 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_allow_reload = true; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1681,7 +1675,7 @@ protected: }; bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { @@ -1772,12 +1766,12 @@ public: m_arguments.push_back (arg1); } - ~CommandObjectCommandsScriptAdd () + ~CommandObjectCommandsScriptAdd () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -1797,11 +1791,10 @@ protected: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1834,7 +1827,7 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_class_name.clear(); m_funct_name.clear(); @@ -1843,7 +1836,7 @@ protected: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1860,8 +1853,8 @@ protected: ScriptedCommandSynchronicity m_synchronicity; }; - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -1872,8 +1865,8 @@ protected: } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); @@ -1935,7 +1928,7 @@ protected: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) @@ -2064,12 +2057,12 @@ public: { } - ~CommandObjectCommandsScriptList () + ~CommandObjectCommandsScriptList () override { } bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { m_interpreter.GetHelp(result, @@ -2100,13 +2093,13 @@ public: { } - ~CommandObjectCommandsScriptClear () + ~CommandObjectCommandsScriptClear () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { m_interpreter.RemoveAllUser(); @@ -2144,13 +2137,13 @@ public: m_arguments.push_back (arg1); } - ~CommandObjectCommandsScriptDelete () + ~CommandObjectCommandsScriptDelete () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { size_t argc = command.GetArgumentCount(); @@ -2202,7 +2195,7 @@ public: LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter))); } - ~CommandObjectMultiwordCommandsScript () + ~CommandObjectMultiwordCommandsScript () override { } diff --git a/source/Commands/CommandObjectCommands.h b/source/Commands/CommandObjectCommands.h index 8a56e8dae6ff..c12c71051ffe 100644 --- a/source/Commands/CommandObjectCommands.h +++ b/source/Commands/CommandObjectCommands.h @@ -30,11 +30,9 @@ public: CommandObjectMultiwordCommands (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordCommands (); - + ~CommandObjectMultiwordCommands() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectCommands_h_ +#endif // liblldb_CommandObjectCommands_h_ diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 1e575fe963f3..100d8692039f 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -289,7 +289,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) if (!m_options.arch.IsValid()) { - result.AppendError ("use the --arch option or set the target architecure to disassemble"); + result.AppendError ("use the --arch option or set the target architecture to disassemble"); result.SetStatus (eReturnStatusFailed); return false; } diff --git a/source/Commands/CommandObjectDisassemble.h b/source/Commands/CommandObjectDisassemble.h index 7a7509858b98..d892824d017d 100644 --- a/source/Commands/CommandObjectDisassemble.h +++ b/source/Commands/CommandObjectDisassemble.h @@ -33,17 +33,16 @@ public: CommandOptions (CommandInterpreter &interpreter); - virtual - ~CommandOptions (); + ~CommandOptions() override; - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg); + Error + SetOptionValue(uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting (); + OptionParsingStarting() override; const OptionDefinition* - GetDefinitions (); + GetDefinitions() override; const char * GetPluginName () @@ -61,8 +60,8 @@ public: return flavor_string.c_str(); } - virtual Error - OptionParsingFinished (); + Error + OptionParsingFinished() override; bool show_mixed; // Show mixed source/assembly bool show_bytes; @@ -86,25 +85,22 @@ public: CommandObjectDisassemble (CommandInterpreter &interpreter); - virtual - ~CommandObjectDisassemble (); + ~CommandObjectDisassemble() override; - virtual Options * - GetOptions () + GetOptions() override { return &m_options; } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result); + bool + DoExecute(Args& command, + CommandReturnObject &result) override; CommandOptions m_options; - }; } // namespace lldb_private -#endif // liblldb_CommandObjectDisassemble_h_ +#endif // liblldb_CommandObjectDisassemble_h_ diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 1be17a0cfddc..7f0b03b37c20 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -16,16 +16,16 @@ #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Expression/ClangFunction.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/REPL.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" #include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Language.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Process.h" @@ -63,6 +63,7 @@ CommandObjectExpression::CommandOptions::g_option_table[] = { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language setting is used." }, { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, NULL, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, }; @@ -84,12 +85,11 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int switch (short_option) { - //case 'l': - //if (language.SetLanguageFromCString (option_arg) == false) - //{ - // error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg); - //} - //break; + case 'l': + language = Language::GetLanguageTypeFromString (option_arg); + if (language == eLanguageTypeUnknown) + error.SetErrorStringWithFormat ("unknown language type: '%s' for expression", option_arg); + break; case 'a': { @@ -180,6 +180,7 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret try_all_threads = true; timeout = 0; debug = false; + language = eLanguageTypeUnknown; m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; } @@ -192,12 +193,13 @@ CommandObjectExpression::CommandOptions::GetDefinitions () CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) : CommandObjectRaw (interpreter, "expression", - "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.", + "Evaluate an expression in the current program context, using user defined variables and variables currently in scope.", NULL, eCommandProcessMustBePaused | eCommandTryTargetAPILock), IOHandlerDelegate (IOHandlerDelegate::Completion::Expression), m_option_group (interpreter), m_format_options (eFormatDefault), + m_repl_option (LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false, true), m_command_options (), m_expr_line_count (0), m_expr_lines () @@ -253,6 +255,7 @@ Examples: m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1); m_option_group.Append (&m_command_options); m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2); + m_option_group.Append (&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); m_option_group.Finalize(); } @@ -288,8 +291,8 @@ CommandObjectExpression::EvaluateExpression if (target) { lldb::ValueObjectSP result_valobj_sp; - bool keep_in_memory = true; + StackFrame *frame = exe_ctx.GetFramePtr(); EvaluateExpressionOptions options; options.SetCoerceToId(m_varobj_options.use_objc); @@ -299,7 +302,8 @@ CommandObjectExpression::EvaluateExpression options.SetUseDynamic(m_varobj_options.use_dynamic); options.SetTryAllThreads(m_command_options.try_all_threads); options.SetDebug(m_command_options.debug); - + options.SetLanguage(m_command_options.language); + // If there is any chance we are going to stop and want to see // what went wrong with our expression, we should generate debug info if (!m_command_options.ignore_breakpoints || @@ -311,8 +315,7 @@ CommandObjectExpression::EvaluateExpression else options.SetTimeoutUsec(0); - target->EvaluateExpression(expr, exe_ctx.GetFramePtr(), - result_valobj_sp, options); + target->EvaluateExpression(expr, frame, result_valobj_sp, options); if (result_valobj_sp) { @@ -326,6 +329,7 @@ CommandObjectExpression::EvaluateExpression result_valobj_sp->SetFormat (format); DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); + options.SetVariableFormatDisplayLanguage(result_valobj_sp->GetPreferredDisplayLanguage()); result_valobj_sp->Dump(*output_stream,options); @@ -335,7 +339,7 @@ CommandObjectExpression::EvaluateExpression } else { - if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) + if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) { if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) { @@ -501,8 +505,70 @@ CommandObjectExpression::DoExecute return false; } + if (m_repl_option.GetOptionValue().GetCurrentValue()) + { + Target *target = m_interpreter.GetExecutionContext().GetTargetPtr(); + if (target) + { + // Drop into REPL + m_expr_lines.clear(); + m_expr_line_count = 0; + + Debugger &debugger = target->GetDebugger(); + + // Check if the LLDB command interpreter is sitting on top of a REPL that + // launched it... + if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter, IOHandler::Type::REPL)) + { + // the LLDB command interpreter is sitting on top of a REPL that launched it, + // so just say the command interpreter is done and fall back to the existing REPL + m_interpreter.GetIOHandler(false)->SetIsDone(true); + } + else + { + // We are launching the REPL on top of the current LLDB command interpreter, + // so just push one + bool initialize = false; + Error repl_error; + REPLSP repl_sp (target->GetREPL(repl_error, m_command_options.language, nullptr, false)); + + if (!repl_sp) + { + initialize = true; + repl_sp = target->GetREPL(repl_error, m_command_options.language, nullptr, true); + if (!repl_error.Success()) + { + result.SetError(repl_error); + return result.Succeeded(); + } + } + + if (repl_sp) + { + if (initialize) + { + repl_sp->SetCommandOptions(m_command_options); + repl_sp->SetFormatOptions(m_format_options); + repl_sp->SetValueObjectDisplayOptions(m_varobj_options); + } + + IOHandlerSP io_handler_sp (repl_sp->GetIOHandler()); + + io_handler_sp->SetIsDone(false); + + debugger.PushIOHandler(io_handler_sp); + } + else + { + repl_error.SetErrorStringWithFormat("Couldn't create a REPL for %s", Language::GetNameForLanguageType(m_command_options.language)); + result.SetError(repl_error); + return result.Succeeded(); + } + } + } + } // No expression following options - if (expr == NULL || expr[0] == '\0') + else if (expr == NULL || expr[0] == '\0') { GetMultilineExpression (); return result.Succeeded(); diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h index 168140d7fe56..7103675f3992 100644 --- a/source/Commands/CommandObjectExpression.h +++ b/source/Commands/CommandObjectExpression.h @@ -16,6 +16,7 @@ // Project includes #include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Target/ExecutionContext.h" @@ -34,22 +35,21 @@ public: CommandOptions (); - virtual - ~CommandOptions (); + ~CommandOptions() override; - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions() override; - virtual const OptionDefinition* - GetDefinitions (); + const OptionDefinition* + GetDefinitions() override; - virtual Error - SetOptionValue (CommandInterpreter &interpreter, - uint32_t option_idx, - const char *option_value); + Error + SetOptionValue(CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override; - virtual void - OptionParsingStarting (CommandInterpreter &interpreter); + void + OptionParsingStarting(CommandInterpreter &interpreter) override; // Options table: Required for subclasses of Options. @@ -61,35 +61,34 @@ public: bool debug; uint32_t timeout; bool try_all_threads; + lldb::LanguageType language; LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; }; CommandObjectExpression (CommandInterpreter &interpreter); - virtual - ~CommandObjectExpression (); + ~CommandObjectExpression() override; - virtual Options * - GetOptions (); + GetOptions() override; protected: //------------------------------------------------------------------ // IOHandler::Delegate functions //------------------------------------------------------------------ - virtual void - IOHandlerInputComplete (IOHandler &io_handler, - std::string &line); + void + IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) override; virtual LineStatus IOHandlerLinesUpdated (IOHandler &io_handler, StringList &lines, uint32_t line_idx, Error &error); - virtual bool - DoExecute (const char *command, - CommandReturnObject &result); + bool + DoExecute(const char *command, + CommandReturnObject &result) override; bool EvaluateExpression (const char *expr, @@ -103,6 +102,7 @@ protected: OptionGroupOptions m_option_group; OptionGroupFormat m_format_options; OptionGroupValueObjectDisplay m_varobj_options; + OptionGroupBoolean m_repl_option; CommandOptions m_command_options; uint32_t m_expr_line_count; std::string m_expr_lines; // Multi-line expression support @@ -110,4 +110,4 @@ protected: } // namespace lldb_private -#endif // liblldb_CommandObjectExpression_h_ +#endif // liblldb_CommandObjectExpression_h_ diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index d8b65e3b551a..9477b50a58df 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -33,8 +33,9 @@ #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionGroupVariable.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -70,13 +71,13 @@ public: { } - ~CommandObjectFrameInfo () + ~CommandObjectFrameInfo () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream()); result.SetStatus (eReturnStatusSuccessFinishResult); @@ -104,13 +105,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; bool success = false; @@ -132,13 +132,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { relative_frame_offset = INT32_MIN; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -174,13 +174,12 @@ public: m_arguments.push_back (arg); } - ~CommandObjectFrameSelect () + ~CommandObjectFrameSelect () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -188,7 +187,7 @@ public: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { // No need to check "thread" for validity as eCommandRequiresThread ensures it is valid Thread *thread = m_exe_ctx.GetThreadPtr(); @@ -263,8 +262,10 @@ protected: } else { - result.AppendError ("invalid arguments.\n"); + result.AppendErrorWithFormat ("too many arguments; expected frame-index, saw '%s'.\n", + command.GetArgumentAtIndex(0)); m_options.GenerateOptionUsage (result.GetErrorStream(), this); + return false; } } @@ -341,20 +342,18 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectFrameVariable () + ~CommandObjectFrameVariable () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_option_group; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -362,7 +361,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { // Arguments are the standard source file completer. std::string completion_str (input.GetArgumentAtIndex(cursor_index)); @@ -380,8 +379,8 @@ public: } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { // No need to check "frame" for validity as eCommandRequiresFrame ensures it is valid StackFrame *frame = m_exe_ctx.GetFramePtr(); @@ -409,6 +408,10 @@ protected: DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp)); + const SymbolContext& sym_ctx = frame->GetSymbolContext(eSymbolContextFunction); + if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction()) + m_option_variable.show_globals = true; + if (variable_list) { const Format format = m_option_format.GetFormat(); @@ -477,7 +480,8 @@ protected: { Error error; uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; + StackFrame::eExpressionPathOptionsAllowDirectIVarAccess | + StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath (name_cstr, m_varobj_options.use_dynamic, @@ -495,6 +499,7 @@ protected: } options.SetFormat(format); + options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); @@ -581,6 +586,7 @@ protected: } options.SetFormat(format); + options.SetVariableFormatDisplayLanguage(valobj_sp->GetPreferredDisplayLanguage()); options.SetRootValueObjectName(name_cstr); valobj_sp->Dump(result.GetOutputStream(),options); } diff --git a/source/Commands/CommandObjectFrame.h b/source/Commands/CommandObjectFrame.h index ea7c808e84b1..a72988078f6d 100644 --- a/source/Commands/CommandObjectFrame.h +++ b/source/Commands/CommandObjectFrame.h @@ -30,11 +30,9 @@ public: CommandObjectMultiwordFrame (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordFrame (); - + ~CommandObjectMultiwordFrame() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectFrame_h_ +#endif // liblldb_CommandObjectFrame_h_ diff --git a/source/Commands/CommandObjectGUI.h b/source/Commands/CommandObjectGUI.h index 72ddb961c266..494bcc48e20e 100644 --- a/source/Commands/CommandObjectGUI.h +++ b/source/Commands/CommandObjectGUI.h @@ -28,16 +28,14 @@ public: CommandObjectGUI (CommandInterpreter &interpreter); - virtual - ~CommandObjectGUI (); + ~CommandObjectGUI() override; protected: - virtual bool - DoExecute (Args& args, - CommandReturnObject &result); - + bool + DoExecute(Args& args, + CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectGUI_h_ +#endif // liblldb_CommandObjectGUI_h_ diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h index 7db659c472c9..1dd7b9b8d6a8 100644 --- a/source/Commands/CommandObjectHelp.h +++ b/source/Commands/CommandObjectHelp.h @@ -29,17 +29,16 @@ public: CommandObjectHelp (CommandInterpreter &interpreter); - virtual - ~CommandObjectHelp (); + ~CommandObjectHelp() override; - virtual int - HandleCompletion (Args &input, - int &cursor_index, - int &cursor_char_position, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches); + int + HandleCompletion(Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) override; class CommandOptions : public Options { @@ -50,11 +49,10 @@ public: { } - virtual - ~CommandOptions (){} + ~CommandOptions() override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue(uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -79,7 +77,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting() override { m_show_aliases = true; m_show_user_defined = true; @@ -87,7 +85,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions() override { return g_option_table; } @@ -103,22 +101,21 @@ public: bool m_show_hidden; }; - virtual Options * - GetOptions () + Options * + GetOptions() override { return &m_options; } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result); + bool + DoExecute(Args& command, + CommandReturnObject &result) override; private: CommandOptions m_options; - }; } // namespace lldb_private -#endif // liblldb_CommandObjectHelp_h_ +#endif // liblldb_CommandObjectHelp_h_ diff --git a/source/Commands/CommandObjectLanguage.cpp b/source/Commands/CommandObjectLanguage.cpp index 9d4b85630a1f..5a8f166cb3a6 100644 --- a/source/Commands/CommandObjectLanguage.cpp +++ b/source/Commands/CommandObjectLanguage.cpp @@ -14,6 +14,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/Language.h" #include "lldb/Target/LanguageRuntime.h" using namespace lldb; @@ -33,10 +34,6 @@ CommandObjectMultiword (interpreter, void CommandObjectLanguage::GenerateHelpText (Stream &output_stream) { CommandObjectMultiword::GenerateHelpText(output_stream); - - output_stream << "\nlanguage name can be one of the following:\n"; - - LanguageRuntime::PrintAllLanguages(output_stream, " ", "\n"); } CommandObjectLanguage::~CommandObjectLanguage () diff --git a/source/Commands/CommandObjectLanguage.h b/source/Commands/CommandObjectLanguage.h index 751fe1440a8b..15902bb8ad4b 100644 --- a/source/Commands/CommandObjectLanguage.h +++ b/source/Commands/CommandObjectLanguage.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes - // Other libraries and framework includes // Project includes @@ -26,11 +25,10 @@ namespace lldb_private { public: CommandObjectLanguage (CommandInterpreter &interpreter); - virtual - ~CommandObjectLanguage (); + ~CommandObjectLanguage() override; - virtual void - GenerateHelpText (Stream &output_stream); + void + GenerateHelpText(Stream &output_stream) override; protected: bool @@ -38,4 +36,4 @@ namespace lldb_private { }; } // namespace lldb_private -#endif // liblldb_CommandObjectLanguage_h_ +#endif // liblldb_CommandObjectLanguage_h_ diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index e68eaf17bb9f..8e29cd5223b0 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -77,13 +77,12 @@ public: m_arguments.push_back (arg2); } - virtual - ~CommandObjectLogEnable() + ~CommandObjectLogEnable() override { } Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -122,13 +121,12 @@ public: } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -154,14 +152,14 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { log_file.Clear(); log_options = 0; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -177,9 +175,9 @@ public: }; protected: - virtual bool + bool DoExecute (Args& args, - CommandReturnObject &result) + CommandReturnObject &result) override { if (args.GetArgumentCount() < 2) { @@ -260,15 +258,14 @@ public: m_arguments.push_back (arg2); } - virtual - ~CommandObjectLogDisable() + ~CommandObjectLogDisable() override { } protected: - virtual bool + bool DoExecute (Args& args, - CommandReturnObject &result) + CommandReturnObject &result) override { const size_t argc = args.GetArgumentCount(); if (argc == 0) @@ -332,15 +329,14 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectLogList() + ~CommandObjectLogList() override { } protected: - virtual bool + bool DoExecute (Args& args, - CommandReturnObject &result) + CommandReturnObject &result) override { const size_t argc = args.GetArgumentCount(); if (argc == 0) @@ -396,15 +392,14 @@ public: { } - virtual - ~CommandObjectLogTimer() + ~CommandObjectLogTimer() override { } protected: - virtual bool + bool DoExecute (Args& args, - CommandReturnObject &result) + CommandReturnObject &result) override { const size_t argc = args.GetArgumentCount(); result.SetStatus(eReturnStatusFailed); diff --git a/source/Commands/CommandObjectLog.h b/source/Commands/CommandObjectLog.h index 3e731fa1d186..be5215f2bdc3 100644 --- a/source/Commands/CommandObjectLog.h +++ b/source/Commands/CommandObjectLog.h @@ -33,8 +33,7 @@ public: //------------------------------------------------------------------ CommandObjectLog(CommandInterpreter &interpreter); - virtual - ~CommandObjectLog(); + ~CommandObjectLog() override; private: //------------------------------------------------------------------ @@ -45,4 +44,4 @@ private: } // namespace lldb_private -#endif // liblldb_CommandObjectLog_h_ +#endif // liblldb_CommandObjectLog_h_ diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index d589800299a3..f8fe456d4d46 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -23,7 +23,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -33,6 +33,7 @@ #include "lldb/Interpreter/OptionGroupOutputFile.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/Process.h" @@ -48,6 +49,7 @@ g_option_table[] = { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, + { LLDB_OPT_SET_3, false , "offset" ,'E', OptionParser::eRequiredArgument, NULL, NULL, 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, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, @@ -62,32 +64,32 @@ public: OptionGroupReadMemory () : m_num_per_line (1,1), m_output_as_binary (false), - m_view_as_type() + m_view_as_type(), + m_offset(0,0) { } - virtual - ~OptionGroupReadMemory () + ~OptionGroupReadMemory () override { } - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions () override { return sizeof (g_option_table) / sizeof (OptionDefinition); } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_option_table; } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_arg) + const char *option_arg) override { Error error; const int short_option = g_option_table[option_idx].short_option; @@ -112,6 +114,10 @@ public: m_force = true; break; + case 'E': + error = m_offset.SetValueFromString(option_arg); + break; + default: error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); break; @@ -119,13 +125,14 @@ public: return error; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { m_num_per_line.Clear(); m_output_as_binary = false; m_view_as_type.Clear(); m_force = false; + m_offset.Clear(); } Error @@ -271,6 +278,7 @@ public: case eFormatVectorOfUInt32: case eFormatVectorOfSInt64: case eFormatVectorOfUInt64: + case eFormatVectorOfFloat16: case eFormatVectorOfFloat32: case eFormatVectorOfFloat64: case eFormatVectorOfUInt128: @@ -290,13 +298,15 @@ public: { return m_num_per_line.OptionWasSet() || m_output_as_binary || - m_view_as_type.OptionWasSet(); + m_view_as_type.OptionWasSet() || + m_offset.OptionWasSet(); } OptionValueUInt64 m_num_per_line; bool m_output_as_binary; OptionValueString m_view_as_type; bool m_force; + OptionValueUInt64 m_offset; }; @@ -366,25 +376,25 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectMemoryRead () + ~CommandObjectMemoryRead () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } - virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + const char * + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override { return m_cmd_name.c_str(); } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid Target *target = m_exe_ctx.GetTargetPtr(); @@ -399,7 +409,7 @@ protected: return false; } - ClangASTType clang_ast_type; + CompilerType clang_ast_type; Error error; const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue(); @@ -526,16 +536,21 @@ protected: 1, type_list); } - + if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$') { - clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name)); - if (tdecl) + if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))) { - clang_ast_type.SetClangType(&tdecl->getASTContext(),(const lldb::clang_type_t)tdecl->getTypeForDecl()); + clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name)); + + if (tdecl) + { + clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()), + reinterpret_cast(const_cast(tdecl->getTypeForDecl()))); + } } } - + if (clang_ast_type.IsValid() == false) { if (type_list.GetSize() == 0) @@ -549,13 +564,13 @@ protected: else { TypeSP type_sp (type_list.GetTypeAtIndex(0)); - clang_ast_type = type_sp->GetClangFullType(); + clang_ast_type = type_sp->GetFullCompilerType (); } } while (pointer_count > 0) { - ClangASTType pointer_type = clang_ast_type.GetPointerType(); + CompilerType pointer_type = clang_ast_type.GetPointerType(); if (pointer_type.IsValid()) clang_ast_type = pointer_type; else @@ -691,6 +706,9 @@ protected: m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue(); + + if (argc > 0) + addr = addr + (clang_ast_type.GetByteSize(nullptr) * m_memory_options.m_offset.GetCurrentValue()); } else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString) { @@ -932,7 +950,7 @@ protected: OptionGroupReadMemory m_prev_memory_options; OptionGroupOutputFile m_prev_outfile_options; OptionGroupValueObjectDisplay m_prev_varobj_options; - ClangASTType m_prev_clang_ast_type; + CompilerType m_prev_clang_ast_type; }; OptionDefinition @@ -961,27 +979,26 @@ public: { } - virtual - ~OptionGroupFindMemory () + ~OptionGroupFindMemory () override { } - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions () override { return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition); } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_memory_find_option_table; } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_arg) + const char *option_arg) override { Error error; const int short_option = g_memory_find_option_table[option_idx].short_option; @@ -1013,8 +1030,8 @@ public: return error; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { m_expr.Clear(); m_string.Clear(); @@ -1042,15 +1059,15 @@ public: CommandArgumentData value_arg; // Define the first (and only) variant of this arg. - addr_arg.arg_type = eArgTypeAddress; + addr_arg.arg_type = eArgTypeAddressOrExpression; addr_arg.arg_repetition = eArgRepeatPlain; // There is only one variant this argument could be; put it into the argument entry. arg1.push_back (addr_arg); // Define the first (and only) variant of this arg. - value_arg.arg_type = eArgTypeValue; - value_arg.arg_repetition = eArgRepeatPlus; + value_arg.arg_type = eArgTypeAddressOrExpression; + value_arg.arg_repetition = eArgRepeatPlain; // There is only one variant this argument could be; put it into the argument entry. arg2.push_back (value_arg); @@ -1063,20 +1080,19 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectMemoryFind () + ~CommandObjectMemoryFind () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); @@ -1119,10 +1135,11 @@ protected: { StackFrame* frame = m_exe_ctx.GetFramePtr(); ValueObjectSP result_sp; - if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get()) + if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) && + result_sp.get()) { uint64_t value = result_sp->GetValueAsUnsigned(0); - switch (result_sp->GetClangType().GetByteSize(nullptr)) + switch (result_sp->GetCompilerType().GetByteSize(nullptr)) { case 1: { uint8_t byte = (uint8_t)value; @@ -1150,13 +1167,13 @@ protected: result.AppendError("unknown type. pass a string instead"); return false; default: - result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead"); + result.AppendError("result size larger than 8 bytes. pass a string instead"); return false; } } else { - result.AppendError("expression evaluation failed. pass a string instead?"); + result.AppendError("expression evaluation failed. pass a string instead"); return false; } } @@ -1176,14 +1193,14 @@ protected: { if (!ever_found) { - result.AppendMessage("Your data was not found within the range.\n"); + result.AppendMessage("data not found within the range.\n"); result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); } else - result.AppendMessage("No more matches found within the range.\n"); + result.AppendMessage("no more matches within the range.\n"); break; } - result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location); + result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location); DataBufferHeap dumpbuffer(32,0); process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error); @@ -1211,27 +1228,16 @@ protected: { Process *process = m_exe_ctx.GetProcessPtr(); DataBufferHeap heap(buffer_size, 0); - lldb::addr_t fictional_ptr = low; for (auto ptr = low; - low < high; - fictional_ptr++) + ptr < high; + ptr++) { Error error; - if (ptr == low || buffer_size == 1) - process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); - else - { - memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1); - process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error); - } + process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); if (error.Fail()) return LLDB_INVALID_ADDRESS; if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) - return fictional_ptr; - if (ptr == low) - ptr += buffer_size; - else - ptr += 1; + return ptr; } return LLDB_INVALID_ADDRESS; } @@ -1263,27 +1269,26 @@ public: { } - virtual - ~OptionGroupWriteMemory () + ~OptionGroupWriteMemory () override { } - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions () override { return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition); } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_memory_write_option_table; } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_arg) + const char *option_arg) override { Error error; const int short_option = g_memory_write_option_table[option_idx].short_option; @@ -1317,8 +1322,8 @@ public: return error; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { m_infile.Clear(); m_infile_offset = 0; @@ -1368,13 +1373,12 @@ public: } - virtual - ~CommandObjectMemoryWrite () + ~CommandObjectMemoryWrite () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } @@ -1407,8 +1411,8 @@ public: } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid Process *process = m_exe_ctx.GetProcessPtr(); @@ -1528,6 +1532,7 @@ protected: case eFormatVectorOfUInt32: case eFormatVectorOfSInt64: case eFormatVectorOfUInt64: + case eFormatVectorOfFloat16: case eFormatVectorOfFloat32: case eFormatVectorOfFloat64: case eFormatVectorOfUInt128: @@ -1716,19 +1721,19 @@ public: m_arguments.push_back (arg1); } - virtual - ~CommandObjectMemoryHistory () + ~CommandObjectMemoryHistory () override { } - virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + const char * + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override { return m_cmd_name.c_str(); } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); diff --git a/source/Commands/CommandObjectMemory.h b/source/Commands/CommandObjectMemory.h index b044921ae077..cf5b4419746c 100644 --- a/source/Commands/CommandObjectMemory.h +++ b/source/Commands/CommandObjectMemory.h @@ -23,11 +23,9 @@ class CommandObjectMemory : public CommandObjectMultiword public: CommandObjectMemory (CommandInterpreter &interpreter); - virtual - ~CommandObjectMemory (); + ~CommandObjectMemory() override; }; - } // namespace lldb_private -#endif // liblldb_CommandObjectMemory_h_ +#endif // liblldb_CommandObjectMemory_h_ diff --git a/source/Commands/CommandObjectMultiword.cpp b/source/Commands/CommandObjectMultiword.cpp index 2f0e2a78a0cc..206f3b6fb7df 100644 --- a/source/Commands/CommandObjectMultiword.cpp +++ b/source/Commands/CommandObjectMultiword.cpp @@ -382,6 +382,14 @@ CommandObjectProxy::IsMultiwordObject () return false; } +void +CommandObjectProxy::GenerateHelpText (Stream &result) +{ + CommandObject *proxy_command = GetProxyCommandObject(); + if (proxy_command) + return proxy_command->GenerateHelpText(result); +} + lldb::CommandObjectSP CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) { diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index a0979d059edb..aad8bea692e7 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -86,15 +86,14 @@ public: { } - virtual - ~OptionPermissions () + ~OptionPermissions () override { } - virtual lldb_private::Error + lldb_private::Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_arg) + const char *option_arg) override { Error error; char short_option = (char) GetDefinitions()[option_idx].short_option; @@ -155,19 +154,19 @@ public: } void - OptionParsingStarting (CommandInterpreter &interpreter) + OptionParsingStarting (CommandInterpreter &interpreter) override { m_permissions = 0; } - virtual uint32_t - GetNumDefinitions () + uint32_t + GetNumDefinitions () override { return llvm::array_lengthof(g_permissions_options); } const lldb_private::OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_permissions_options; } @@ -198,19 +197,18 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectPlatformSelect () + ~CommandObjectPlatformSelect () override { } - virtual int + int HandleCompletion (Args &input, int &cursor_index, int &cursor_char_position, int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -225,15 +223,15 @@ public: return matches.GetSize(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 1) { @@ -291,14 +289,13 @@ public: { } - virtual - ~CommandObjectPlatformList () + ~CommandObjectPlatformList () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); ostrm.Printf("Available platforms:\n"); @@ -346,14 +343,13 @@ public: { } - virtual - ~CommandObjectPlatformStatus () + ~CommandObjectPlatformStatus () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); @@ -396,14 +392,13 @@ public: { } - virtual - ~CommandObjectPlatformConnect () + ~CommandObjectPlatformConnect () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Stream &ostrm = result.GetOutputStream(); @@ -414,12 +409,19 @@ protected: if (error.Success()) { platform_sp->GetStatus (ostrm); - result.SetStatus (eReturnStatusSuccessFinishResult); + result.SetStatus (eReturnStatusSuccessFinishResult); + + platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(), error); + if (error.Fail()) + { + result.AppendError (error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } } else { result.AppendErrorWithFormat ("%s\n", error.AsCString()); - result.SetStatus (eReturnStatusFailed); + result.SetStatus (eReturnStatusFailed); } } else @@ -430,8 +432,8 @@ protected: return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); OptionGroupOptions* m_platform_options = NULL; @@ -461,14 +463,13 @@ public: { } - virtual - ~CommandObjectPlatformDisconnect () + ~CommandObjectPlatformDisconnect () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -543,14 +544,13 @@ public: m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); } - virtual - ~CommandObjectPlatformSettings () + ~CommandObjectPlatformSettings () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -566,8 +566,8 @@ protected: return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { if (m_options.DidFinalize() == false) m_options.Finalize(); @@ -597,13 +597,12 @@ public: { } - virtual - ~CommandObjectPlatformMkDir () + ~CommandObjectPlatformMkDir () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -635,8 +634,8 @@ public: return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { if (m_options.DidFinalize() == false) { @@ -665,13 +664,12 @@ public: { } - virtual - ~CommandObjectPlatformFOpen () + ~CommandObjectPlatformFOpen () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -708,8 +706,8 @@ public: } return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { if (m_options.DidFinalize() == false) { @@ -736,13 +734,12 @@ public: { } - virtual - ~CommandObjectPlatformFClose () + ~CommandObjectPlatformFClose () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -788,13 +785,12 @@ public: { } - virtual - ~CommandObjectPlatformFRead () + ~CommandObjectPlatformFRead () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -816,8 +812,8 @@ public: } return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -832,13 +828,12 @@ protected: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; char short_option = (char) m_getopt_table[option_idx].val; @@ -866,14 +861,14 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_offset = 0; m_count = 1; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -914,13 +909,12 @@ public: { } - virtual - ~CommandObjectPlatformFWrite () + ~CommandObjectPlatformFWrite () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -944,8 +938,8 @@ public: } return result.Succeeded(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -960,13 +954,12 @@ protected: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; char short_option = (char) m_getopt_table[option_idx].val; @@ -992,14 +985,14 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_offset = 0; m_data.clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1041,8 +1034,7 @@ public: LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter))); } - virtual - ~CommandObjectPlatformFile () + ~CommandObjectPlatformFile () override { } @@ -1094,13 +1086,12 @@ R"(Examples: m_arguments.push_back (arg2); } - virtual - ~CommandObjectPlatformGetFile () + ~CommandObjectPlatformGetFile () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 2) @@ -1172,13 +1163,12 @@ R"(Examples: m_arguments.push_back (arg1); } - virtual - ~CommandObjectPlatformGetSize () + ~CommandObjectPlatformGetSize () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { // If the number of arguments is incorrect, issue an error message. if (args.GetArgumentCount() != 1) @@ -1228,13 +1218,12 @@ public: { } - virtual - ~CommandObjectPlatformPutFile () + ~CommandObjectPlatformPutFile () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { const char* src = args.GetArgumentAtIndex(0); const char* dst = args.GetArgumentAtIndex(1); @@ -1281,20 +1270,19 @@ public: { } - virtual - ~CommandObjectPlatformProcessLaunch () + ~CommandObjectPlatformProcessLaunch () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; @@ -1398,20 +1386,19 @@ public: { } - virtual - ~CommandObjectPlatformProcessList () + ~CommandObjectPlatformProcessList () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; @@ -1524,13 +1511,12 @@ protected: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1620,7 +1606,7 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { match_info.Clear(); show_args = false; @@ -1628,7 +1614,7 @@ protected: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1698,14 +1684,13 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectPlatformProcessInfo () + ~CommandObjectPlatformProcessInfo () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); PlatformSP platform_sp; @@ -1793,12 +1778,12 @@ public: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; char short_option = (char) m_getopt_table[option_idx].val; @@ -1839,18 +1824,18 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { attach_info.Clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } - virtual bool + bool HandleOptionArgumentCompletion (Args &input, int cursor_index, int char_pos, @@ -1859,7 +1844,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; @@ -1921,13 +1906,13 @@ public: { } - ~CommandObjectPlatformProcessAttach () + ~CommandObjectPlatformProcessAttach () override { } bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); if (platform_sp) @@ -1957,7 +1942,7 @@ public: } Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -1998,8 +1983,7 @@ public: } - virtual - ~CommandObjectPlatformProcess () + ~CommandObjectPlatformProcess () override { } @@ -2027,8 +2011,7 @@ public: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } @@ -2038,15 +2021,15 @@ public: return 1; } - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_option_table; } - virtual Error + Error SetOptionValue (uint32_t option_idx, - const char *option_value) + const char *option_value) override { Error error; @@ -2070,8 +2053,8 @@ public: return error; } - virtual void - OptionParsingStarting () + void + OptionParsingStarting () override { } @@ -2091,20 +2074,18 @@ public: { } - virtual - ~CommandObjectPlatformShell () + ~CommandObjectPlatformShell () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } - virtual bool - DoExecute (const char *raw_command_line, CommandReturnObject &result) + bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) override { m_options.NotifyOptionParsingStarting(); @@ -2218,13 +2199,12 @@ public: { } - virtual - ~CommandObjectPlatformInstall () + ~CommandObjectPlatformInstall () override { } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { if (args.GetArgumentCount() != 2) { diff --git a/source/Commands/CommandObjectPlatform.h b/source/Commands/CommandObjectPlatform.h index f3bd75848649..023dff9f9827 100644 --- a/source/Commands/CommandObjectPlatform.h +++ b/source/Commands/CommandObjectPlatform.h @@ -28,13 +28,12 @@ class CommandObjectPlatform : public CommandObjectMultiword public: CommandObjectPlatform(CommandInterpreter &interpreter); - virtual - ~CommandObjectPlatform(); + ~CommandObjectPlatform() override; - private: +private: DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatform); }; } // namespace lldb_private -#endif // liblldb_CommandObjectPlatform_h_ +#endif // liblldb_CommandObjectPlatform_h_ diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp index 63fa4a82cf91..4c5a089dbcec 100644 --- a/source/Commands/CommandObjectPlugin.cpp +++ b/source/Commands/CommandObjectPlugin.cpp @@ -41,7 +41,7 @@ public: m_arguments.push_back (arg1); } - ~CommandObjectPluginLoad () + ~CommandObjectPluginLoad () override { } @@ -53,7 +53,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -71,7 +71,7 @@ public: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { size_t argc = command.GetArgumentCount(); diff --git a/source/Commands/CommandObjectPlugin.h b/source/Commands/CommandObjectPlugin.h index 9d0f0fcc1ed3..0a96041d2d31 100644 --- a/source/Commands/CommandObjectPlugin.h +++ b/source/Commands/CommandObjectPlugin.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes - // Other libraries and framework includes // Project includes @@ -27,10 +26,9 @@ namespace lldb_private { public: CommandObjectPlugin (CommandInterpreter &interpreter); - virtual - ~CommandObjectPlugin (); + ~CommandObjectPlugin() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectPlugin_h_ +#endif // liblldb_CommandObjectPlugin_h_ diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index e587eadfa3d6..b7f894f6dcf5 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -47,7 +47,7 @@ public: CommandObjectParsed (interpreter, name, help, syntax, flags), m_new_process_action (new_process_action) {} - virtual ~CommandObjectProcessLaunchOrAttach () {} + ~CommandObjectProcessLaunchOrAttach () override {} protected: bool StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result) @@ -142,11 +142,11 @@ public: } - ~CommandObjectProcessLaunch () + ~CommandObjectProcessLaunch () override { } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -154,7 +154,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -171,12 +171,13 @@ public: } Options * - GetOptions () + GetOptions () override { return &m_options; } - virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + const char * + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override { // No repeat for "process launch"... return ""; @@ -184,7 +185,7 @@ public: protected: bool - DoExecute (Args& launch_args, CommandReturnObject &result) + DoExecute (Args& launch_args, CommandReturnObject &result) override { Debugger &debugger = m_interpreter.GetDebugger(); Target *target = debugger.GetSelectedTarget().get(); @@ -338,12 +339,12 @@ public: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -392,18 +393,18 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { attach_info.Clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } - virtual bool + bool HandleOptionArgumentCompletion (Args &input, int cursor_index, int char_pos, @@ -412,7 +413,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; @@ -476,20 +477,19 @@ public: { } - ~CommandObjectProcessAttach () + ~CommandObjectProcessAttach () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); @@ -646,7 +646,7 @@ public: } - ~CommandObjectProcessContinue () + ~CommandObjectProcessContinue () override { } @@ -663,12 +663,12 @@ protected: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -689,13 +689,13 @@ protected: } void - OptionParsingStarting () + OptionParsingStarting () override { m_ignore = 0; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -708,7 +708,7 @@ protected: }; bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); bool synchronous_execution = m_interpreter.GetSynchronous (); @@ -807,7 +807,7 @@ protected: } Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -842,12 +842,12 @@ public: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -876,13 +876,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_keep_stopped = eLazyBoolCalculate; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -907,12 +907,12 @@ public: { } - ~CommandObjectProcessDetach () + ~CommandObjectProcessDetach () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -920,7 +920,7 @@ public: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); // FIXME: This will be a Command Option: @@ -982,12 +982,12 @@ public: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1006,13 +1006,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { plugin_name.clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1036,94 +1036,61 @@ public: { } - ~CommandObjectProcessConnect () + ~CommandObjectProcessConnect () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { - - TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget()); - Error error; - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) + if (command.GetArgumentCount() != 1) { - if (process->IsAlive()) - { - result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", - process->GetID()); - result.SetStatus (eReturnStatusFailed); - return false; - } + result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", + m_cmd_name.c_str(), + m_cmd_syntax.c_str()); + result.SetStatus (eReturnStatusFailed); + return false; } + - if (!target_sp) + Process *process = m_exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) { - // If there isn't a current target create one. - - error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), - NULL, - NULL, - false, - NULL, // No platform options - target_sp); - if (!target_sp || error.Fail()) - { - result.AppendError(error.AsCString("Error creating target")); - result.SetStatus (eReturnStatusFailed); - return false; - } - m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get()); + result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", + process->GetID()); + result.SetStatus (eReturnStatusFailed); + return false; } - - if (command.GetArgumentCount() == 1) - { - const char *plugin_name = NULL; - if (!m_options.plugin_name.empty()) - plugin_name = m_options.plugin_name.c_str(); - const char *remote_url = command.GetArgumentAtIndex(0); - process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); - - if (process) - { - error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url); + const char *plugin_name = nullptr; + if (!m_options.plugin_name.empty()) + plugin_name = m_options.plugin_name.c_str(); - if (error.Fail()) - { - result.AppendError(error.AsCString("Remote connect failed")); - result.SetStatus (eReturnStatusFailed); - target_sp->DeleteCurrentProcess(); - return false; - } - } - else - { - result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n", - remote_url); - result.SetStatus (eReturnStatusFailed); - } - } - else + Error error; + Debugger& debugger = m_interpreter.GetDebugger(); + PlatformSP platform_sp = m_interpreter.GetPlatform(true); + ProcessSP process_sp = platform_sp->ConnectProcess(command.GetArgumentAtIndex(0), + plugin_name, + debugger, + debugger.GetSelectedTarget().get(), + error); + if (error.Fail() || process_sp == nullptr) { - result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", - m_cmd_name.c_str(), - m_cmd_syntax.c_str()); + result.AppendError(error.AsCString("Error connecting to the process")); result.SetStatus (eReturnStatusFailed); + return false; } - return result.Succeeded(); + return true; } - + CommandOptions m_options; }; @@ -1152,12 +1119,12 @@ public: { } - ~CommandObjectProcessPlugin () + ~CommandObjectProcessPlugin () override { } - virtual CommandObject * - GetProxyCommandObject() + CommandObject * + GetProxyCommandObject() override { Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) @@ -1175,6 +1142,57 @@ public: class CommandObjectProcessLoad : public CommandObjectParsed { public: + class CommandOptions : public Options + { + public: + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) + { + // Keep default values of all options in one place: OptionParsingStarting () + OptionParsingStarting (); + } + + ~CommandOptions () override = default; + + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + switch (short_option) + { + case 'i': + do_install = true; + if (option_arg && option_arg[0]) + install_path.SetFile(option_arg, false); + break; + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + } + return error; + } + + void + OptionParsingStarting () override + { + do_install = false; + install_path.Clear(); + } + + const OptionDefinition* + GetDefinitions () override + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + bool do_install; + FileSpec install_path; + }; CommandObjectProcessLoad (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, @@ -1184,33 +1202,54 @@ public: eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ) + eCommandProcessMustBePaused ), + m_options (interpreter) { } - ~CommandObjectProcessLoad () + ~CommandObjectProcessLoad () override = default; + + Options * + GetOptions () override { + return &m_options; } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); const size_t argc = command.GetArgumentCount(); - for (uint32_t i=0; iGetTarget().GetPlatform(); const char *image_path = command.GetArgumentAtIndex(i); - FileSpec image_spec (image_path, false); - process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec); - uint32_t image_token = process->LoadImage(image_spec, error); + uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; + + if (!m_options.do_install) + { + FileSpec image_spec (image_path, false); + 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); + 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); + image_token = platform->LoadImage(process, image_spec, FileSpec(), error); + } + if (image_token != LLDB_INVALID_IMAGE_TOKEN) { - result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); + result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); result.SetStatus (eReturnStatusSuccessFinishResult); } else @@ -1221,8 +1260,16 @@ protected: } return result.Succeeded(); } + + CommandOptions m_options; }; +OptionDefinition +CommandObjectProcessLoad::CommandOptions::g_option_table[] = +{ + { 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."}, + { 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } +}; //------------------------------------------------------------------------- // CommandObjectProcessUnload @@ -1245,14 +1292,13 @@ public: { } - ~CommandObjectProcessUnload () + ~CommandObjectProcessUnload () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); @@ -1270,7 +1316,7 @@ protected: } else { - Error error (process->UnloadImage(image_token)); + Error error (process->GetTarget().GetPlatform()->UnloadImage(process, image_token)); if (error.Success()) { result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); @@ -1318,14 +1364,13 @@ public: m_arguments.push_back (arg); } - ~CommandObjectProcessSignal () + ~CommandObjectProcessSignal () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); @@ -1390,14 +1435,13 @@ public: { } - ~CommandObjectProcessInterrupt () + ~CommandObjectProcessInterrupt () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == NULL) @@ -1452,14 +1496,13 @@ public: { } - ~CommandObjectProcessKill () + ~CommandObjectProcessKill () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == NULL) @@ -1513,14 +1556,14 @@ public: { } - ~CommandObjectProcessSaveCore () + ~CommandObjectProcessSaveCore () override { } protected: bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); if (process_sp) @@ -1575,13 +1618,13 @@ public: { } - ~CommandObjectProcessStatus() + ~CommandObjectProcessStatus() override { } bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1620,12 +1663,12 @@ public: OptionParsingStarting (); } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1649,7 +1692,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { stop.clear(); notify.clear(); @@ -1657,7 +1700,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1694,12 +1737,12 @@ public: m_arguments.push_back (arg); } - ~CommandObjectProcessHandle () + ~CommandObjectProcessHandle () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -1781,7 +1824,7 @@ public: protected: bool - DoExecute (Args &signal_args, CommandReturnObject &result) + DoExecute (Args &signal_args, CommandReturnObject &result) override { TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); diff --git a/source/Commands/CommandObjectProcess.h b/source/Commands/CommandObjectProcess.h index 0aaa74d28a07..804c34261bad 100644 --- a/source/Commands/CommandObjectProcess.h +++ b/source/Commands/CommandObjectProcess.h @@ -27,11 +27,9 @@ class CommandObjectMultiwordProcess : public CommandObjectMultiword public: CommandObjectMultiwordProcess (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordProcess (); - + ~CommandObjectMultiwordProcess() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectProcess_h_ +#endif // liblldb_CommandObjectProcess_h_ diff --git a/source/Commands/CommandObjectQuit.h b/source/Commands/CommandObjectQuit.h index aab0e26cce59..df9216b7e7e3 100644 --- a/source/Commands/CommandObjectQuit.h +++ b/source/Commands/CommandObjectQuit.h @@ -28,19 +28,17 @@ public: CommandObjectQuit (CommandInterpreter &interpreter); - virtual - ~CommandObjectQuit (); + ~CommandObjectQuit() override; protected: - virtual bool - DoExecute (Args& args, - CommandReturnObject &result); + bool + DoExecute(Args& args, + CommandReturnObject &result) override; bool ShouldAskForConfirmation (bool& is_a_detach); - }; } // namespace lldb_private -#endif // liblldb_CommandObjectQuit_h_ +#endif // liblldb_CommandObjectQuit_h_ diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index fae5af42f405..23a215763738 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -74,13 +74,12 @@ public: } - virtual - ~CommandObjectRegisterRead () + ~CommandObjectRegisterRead () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } @@ -170,8 +169,8 @@ public: } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); @@ -271,33 +270,32 @@ protected: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions () override; - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_option_table; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { set_indexes.Clear(); dump_all_sets.Clear(); alternate_name.Clear(); } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_value) + const char *option_value) override { Error error; const int short_option = g_option_table[option_idx].short_option; @@ -404,14 +402,13 @@ public: m_arguments.push_back (arg2); } - virtual - ~CommandObjectRegisterWrite () + ~CommandObjectRegisterWrite () override { } protected: - virtual bool - DoExecute(Args& command, CommandReturnObject &result) + bool + DoExecute(Args& command, CommandReturnObject &result) override { DataExtractor reg_data; RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext (); diff --git a/source/Commands/CommandObjectRegister.h b/source/Commands/CommandObjectRegister.h index 7f856c2de529..e7b6974bc998 100644 --- a/source/Commands/CommandObjectRegister.h +++ b/source/Commands/CommandObjectRegister.h @@ -30,8 +30,7 @@ public: //------------------------------------------------------------------ CommandObjectRegister(CommandInterpreter &interpreter); - virtual - ~CommandObjectRegister(); + ~CommandObjectRegister() override; private: //------------------------------------------------------------------ @@ -42,4 +41,4 @@ private: } // namespace lldb_private -#endif // liblldb_CommandObjectRegister_h_ +#endif // liblldb_CommandObjectRegister_h_ diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp index 8ed783b211f6..890d77028a99 100644 --- a/source/Commands/CommandObjectSettings.cpp +++ b/source/Commands/CommandObjectSettings.cpp @@ -83,15 +83,14 @@ insert-before or insert-after." } - virtual - ~CommandObjectSettingsSet () {} + ~CommandObjectSettingsSet () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -106,11 +105,10 @@ insert-before or insert-after." { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -129,13 +127,13 @@ insert-before or insert-after." } void - OptionParsingStarting () + OptionParsingStarting () override { m_global = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -149,7 +147,7 @@ insert-before or insert-after." bool m_global; }; - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -157,7 +155,7 @@ insert-before or insert-after." int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -215,8 +213,8 @@ insert-before or insert-after." } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { Args cmd_args(command); @@ -321,11 +319,10 @@ public: m_arguments.push_back (arg1); } - virtual - ~CommandObjectSettingsShow () {} + ~CommandObjectSettingsShow () override {} - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -333,7 +330,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -349,8 +346,8 @@ public: } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishResult); @@ -414,10 +411,9 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectSettingsList () {} + ~CommandObjectSettingsList () override {} - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -425,7 +421,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -441,8 +437,8 @@ public: } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishResult); @@ -521,10 +517,9 @@ public: m_arguments.push_back (arg2); } - virtual - ~CommandObjectSettingsRemove () {} + ~CommandObjectSettingsRemove () override {} - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -532,7 +527,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -551,8 +546,8 @@ public: } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -652,14 +647,13 @@ public: } - virtual - ~CommandObjectSettingsReplace () {} + ~CommandObjectSettingsReplace () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -667,7 +661,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -686,8 +680,8 @@ public: } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -773,14 +767,13 @@ public: m_arguments.push_back (arg3); } - virtual - ~CommandObjectSettingsInsertBefore () {} + ~CommandObjectSettingsInsertBefore () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -788,7 +781,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -807,8 +800,8 @@ public: } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -897,14 +890,13 @@ public: m_arguments.push_back (arg3); } - virtual - ~CommandObjectSettingsInsertAfter () {} + ~CommandObjectSettingsInsertAfter () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -912,7 +904,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -931,8 +923,8 @@ public: } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1011,14 +1003,13 @@ public: m_arguments.push_back (arg2); } - virtual - ~CommandObjectSettingsAppend () {} + ~CommandObjectSettingsAppend () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -1026,7 +1017,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -1045,8 +1036,8 @@ public: } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); Args cmd_args(command); @@ -1117,10 +1108,9 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectSettingsClear () {} + ~CommandObjectSettingsClear () override {} - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -1128,7 +1118,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position); @@ -1147,8 +1137,8 @@ public: } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { result.SetStatus (eReturnStatusSuccessFinishNoResult); const size_t argc = command.GetArgumentCount (); diff --git a/source/Commands/CommandObjectSettings.h b/source/Commands/CommandObjectSettings.h index eca7adeea76f..93ee91981c10 100644 --- a/source/Commands/CommandObjectSettings.h +++ b/source/Commands/CommandObjectSettings.h @@ -31,11 +31,9 @@ public: CommandObjectMultiwordSettings (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordSettings (); - + ~CommandObjectMultiwordSettings() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectSettings_h_ +#endif // liblldb_CommandObjectSettings_h_ diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 7c5f127cb51a..08c8d46d1ee0 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -49,12 +49,12 @@ class CommandObjectSourceInfo : public CommandObjectParsed { } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = g_option_table[option_idx].short_option; @@ -79,7 +79,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed } void - OptionParsingStarting () + OptionParsingStarting () override { file_spec.Clear(); file_name.clear(); @@ -87,7 +87,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -110,20 +110,20 @@ public: { } - ~CommandObjectSourceInfo () + ~CommandObjectSourceInfo () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { result.AppendError ("Not yet implemented"); result.SetStatus (eReturnStatusFailed); @@ -157,12 +157,12 @@ class CommandObjectSourceList : public CommandObjectParsed { } - ~CommandOptions () + ~CommandOptions () override { } Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = g_option_table[option_idx].short_option; @@ -213,7 +213,7 @@ class CommandObjectSourceList : public CommandObjectParsed } void - OptionParsingStarting () + OptionParsingStarting () override { file_spec.Clear(); file_name.clear(); @@ -227,7 +227,7 @@ class CommandObjectSourceList : public CommandObjectParsed } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -256,19 +256,19 @@ public: { } - ~CommandObjectSourceList () + ~CommandObjectSourceList () override { } Options * - GetOptions () + GetOptions () override { return &m_options; } - virtual const char * - GetRepeatCommand (Args ¤t_command_args, uint32_t index) + const char * + GetRepeatCommand (Args ¤t_command_args, uint32_t index) override { // This is kind of gross, but the command hasn't been parsed yet so we can't look at the option // values for this invocation... I have to scan the arguments directly. @@ -507,7 +507,7 @@ protected: } bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); diff --git a/source/Commands/CommandObjectSource.h b/source/Commands/CommandObjectSource.h index 0daef1385860..7ed08cdc9591 100644 --- a/source/Commands/CommandObjectSource.h +++ b/source/Commands/CommandObjectSource.h @@ -30,11 +30,9 @@ public: CommandObjectMultiwordSource (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordSource (); - + ~CommandObjectMultiwordSource() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectSource.h_h_ +#endif // liblldb_CommandObjectSource_h_ diff --git a/source/Commands/CommandObjectSyntax.h b/source/Commands/CommandObjectSyntax.h index 47bf85f8549e..1a3e4e04f01a 100644 --- a/source/Commands/CommandObjectSyntax.h +++ b/source/Commands/CommandObjectSyntax.h @@ -28,17 +28,14 @@ public: CommandObjectSyntax (CommandInterpreter &interpreter); - virtual - ~CommandObjectSyntax (); + ~CommandObjectSyntax() override; protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result); - - + bool + DoExecute(Args& command, + CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectSyntax_h_ +#endif // liblldb_CommandObjectSyntax_h_ diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index 448da0ede245..026ae3570854 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -79,7 +79,8 @@ DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bo uint32_t properties = 0; if (target_arch.IsValid()) { - strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str()); + strm.Printf ("%sarch=", properties++ > 0 ? ", " : " ( "); + target_arch.DumpTriple (strm); properties++; } PlatformSP platform_sp (target->GetPlatform()); @@ -187,17 +188,17 @@ public: m_option_group.Finalize(); } - ~CommandObjectTargetCreate () + ~CommandObjectTargetCreate () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -205,7 +206,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -223,7 +224,7 @@ public: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue()); @@ -255,7 +256,7 @@ protected: { if (!symfile.Readable()) { - result.AppendErrorWithFormat("symbol file '%s' is not readable", core_file.GetPath().c_str()); + result.AppendErrorWithFormat("symbol file '%s' is not readable", symfile.GetPath().c_str()); result.SetStatus (eReturnStatusFailed); return false; } @@ -401,7 +402,7 @@ protected: if (process_sp) { - // Seems wierd that we Launch a core file, but that is + // Seems weird that we Launch a core file, but that is // what we do! error = process_sp->LoadCore(); @@ -477,14 +478,13 @@ public: { } - virtual - ~CommandObjectTargetList () + ~CommandObjectTargetList () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 0) { @@ -525,14 +525,13 @@ public: { } - virtual - ~CommandObjectTargetSelect () + ~CommandObjectTargetSelect () override { } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { if (args.GetArgumentCount() == 1) { @@ -622,20 +621,19 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectTargetDelete () + ~CommandObjectTargetDelete () override { } Options * - GetOptions () + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { const size_t argc = args.GetArgumentCount(); std::vector delete_target_list; @@ -777,8 +775,7 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectTargetVariable () + ~CommandObjectTargetVariable () override { } @@ -850,7 +847,7 @@ public: } Options * - GetOptions () + GetOptions () override { return &m_option_group; } @@ -896,8 +893,8 @@ protected: } } - virtual bool - DoExecute (Args& args, CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); const size_t argc = args.GetArgumentCount(); @@ -1134,14 +1131,13 @@ public: m_arguments.push_back (arg); } - ~CommandObjectTargetModulesSearchPathsAdd () + ~CommandObjectTargetModulesSearchPathsAdd () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) @@ -1161,6 +1157,12 @@ protected: if (from[0] && to[0]) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + { + log->Printf ("target modules search path adding ImageSearchPath pair: '%s' -> '%s'", + from, to); + } bool last_pair = ((argc - i) == 2); target->GetImageSearchPathList().Append (ConstString(from), ConstString(to), @@ -1201,14 +1203,13 @@ public: { } - ~CommandObjectTargetModulesSearchPathsClear () + ~CommandObjectTargetModulesSearchPathsClear () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) @@ -1271,20 +1272,19 @@ public: m_arguments.push_back (arg2); } - ~CommandObjectTargetModulesSearchPathsInsert () + ~CommandObjectTargetModulesSearchPathsInsert () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) { size_t argc = command.GetArgumentCount(); - // check for at least 3 arguments and an odd nubmer of parameters + // check for at least 3 arguments and an odd number of parameters if (argc >= 3 && argc & 1) { bool success = false; @@ -1360,14 +1360,13 @@ public: { } - ~CommandObjectTargetModulesSearchPathsList () + ~CommandObjectTargetModulesSearchPathsList () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) @@ -1417,14 +1416,13 @@ public: m_arguments.push_back (arg); } - ~CommandObjectTargetModulesSearchPathsQuery () + ~CommandObjectTargetModulesSearchPathsQuery () override { } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target) @@ -1462,15 +1460,18 @@ DumpModuleArchitecture (Stream &strm, Module *module, bool full_triple, uint32_t { if (module) { - const char *arch_cstr; + StreamString arch_strm; + if (full_triple) - arch_cstr = module->GetArchitecture().GetTriple().str().c_str(); + module->GetArchitecture().DumpTriple(arch_strm); else - arch_cstr = module->GetArchitecture().GetArchitectureName(); + arch_strm.PutCString(module->GetArchitecture().GetArchitectureName()); + std::string arch_str = arch_strm.GetString(); + if (width) - strm.Printf("%-*s", width, arch_cstr); + strm.Printf("%-*s", width, arch_str.c_str()); else - strm.PutCString(arch_cstr); + strm.PutCString(arch_str.c_str()); } } @@ -1865,7 +1866,7 @@ LookupTypeInModule (CommandInterpreter &interpreter, { // Resolve the clang type so that any forward references // to types that haven't yet been parsed will get parsed. - type_sp->GetClangFullType (); + type_sp->GetFullCompilerType (); type_sp->GetDescription (&strm, eDescriptionLevelFull, true); // Print all typedef chains TypeSP typedef_type_sp (type_sp); @@ -1874,7 +1875,7 @@ LookupTypeInModule (CommandInterpreter &interpreter, { strm.EOL(); strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetClangFullType (); + typedefed_type_sp->GetFullCompilerType (); typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true); typedef_type_sp = typedefed_type_sp; typedefed_type_sp = typedef_type_sp->GetTypedefType(); @@ -1918,7 +1919,7 @@ LookupTypeHere (CommandInterpreter &interpreter, { // Resolve the clang type so that any forward references // to types that haven't yet been parsed will get parsed. - type_sp->GetClangFullType (); + type_sp->GetFullCompilerType (); type_sp->GetDescription (&strm, eDescriptionLevelFull, true); // Print all typedef chains TypeSP typedef_type_sp (type_sp); @@ -1927,7 +1928,7 @@ LookupTypeHere (CommandInterpreter &interpreter, { strm.EOL(); strm.Printf(" typedef '%s': ", typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetClangFullType (); + typedefed_type_sp->GetFullCompilerType (); typedefed_type_sp->GetDescription (&strm, eDescriptionLevelFull, true); typedef_type_sp = typedefed_type_sp; typedefed_type_sp = typedef_type_sp->GetTypedefType(); @@ -2056,12 +2057,11 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectTargetModulesModuleAutoComplete () + ~CommandObjectTargetModulesModuleAutoComplete () override { } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -2069,7 +2069,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { // Arguments are the standard module completer. std::string completion_str (input.GetArgumentAtIndex(cursor_index)); @@ -2118,12 +2118,11 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectTargetModulesSourceFileAutoComplete () + ~CommandObjectTargetModulesSourceFileAutoComplete () override { } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -2131,7 +2130,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { // Arguments are the standard source file completer. std::string completion_str (input.GetArgumentAtIndex(cursor_index)); @@ -2165,13 +2164,12 @@ public: { } - virtual - ~CommandObjectTargetModulesDumpSymtab () + ~CommandObjectTargetModulesDumpSymtab () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -2185,13 +2183,12 @@ public: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -2214,13 +2211,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_sort_order = eSortOrderNone; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -2232,9 +2229,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -2359,15 +2355,13 @@ public: { } - virtual - ~CommandObjectTargetModulesDumpSections () + ~CommandObjectTargetModulesDumpSections () override { } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -2465,15 +2459,13 @@ public: { } - virtual - ~CommandObjectTargetModulesDumpSymfile () + ~CommandObjectTargetModulesDumpSymfile () override { } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -2568,15 +2560,13 @@ public: { } - virtual - ~CommandObjectTargetModulesDumpLineTable () + ~CommandObjectTargetModulesDumpLineTable () override { } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); uint32_t total_num_dumped = 0; @@ -2657,8 +2647,7 @@ public: LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter))); } - virtual - ~CommandObjectTargetModulesDump() + ~CommandObjectTargetModulesDump() override { } }; @@ -2679,18 +2668,17 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectTargetModulesAdd () + ~CommandObjectTargetModulesAdd () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -2698,7 +2686,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -2719,9 +2707,8 @@ protected: OptionGroupUUID m_uuid_option_group; OptionGroupFile m_symbol_file; - virtual bool - DoExecute (Args& args, - CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -2882,21 +2869,19 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectTargetModulesLoad () + ~CommandObjectTargetModulesLoad () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (Args& args, - CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -3139,13 +3124,12 @@ public: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; @@ -3170,7 +3154,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_format_array.clear(); m_use_global_module_list = false; @@ -3178,7 +3162,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -3203,22 +3187,19 @@ public: { } - virtual - ~CommandObjectTargetModulesList () + ~CommandObjectTargetModulesList () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); const bool use_global_module_list = m_options.m_use_global_module_list; @@ -3584,13 +3565,12 @@ public: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; @@ -3625,7 +3605,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_type = eLookupTypeInvalid; m_str.clear(); @@ -3633,7 +3613,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -3662,22 +3642,19 @@ public: { } - virtual - ~CommandObjectTargetModulesShowUnwind () + ~CommandObjectTargetModulesShowUnwind () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } protected: bool - DoExecute (Args& command, - CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); Process *process = m_exe_ctx.GetProcessPtr(); @@ -3813,6 +3790,14 @@ protected: result.GetOutputStream().Printf("\n"); } + UnwindPlanSP arm_unwind_sp = func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0); + if (arm_unwind_sp) + { + result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n"); + arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(), LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + UnwindPlanSP compact_unwind_sp = func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0); if (compact_unwind_sp) { @@ -3891,13 +3876,12 @@ public: OptionParsingStarting(); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; @@ -3974,7 +3958,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_type = eLookupTypeInvalid; m_str.clear(); @@ -3989,7 +3973,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -4031,13 +4015,12 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectTargetModulesLookup () + ~CommandObjectTargetModulesLookup () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -4191,9 +4174,8 @@ public: } protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -4339,7 +4321,7 @@ public: LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter))); } - ~CommandObjectTargetModulesImageSearchPaths() + ~CommandObjectTargetModulesImageSearchPaths() override { } }; @@ -4373,8 +4355,8 @@ public: LoadSubCommand ("show-unwind", CommandObjectSP (new CommandObjectTargetModulesShowUnwind (interpreter))); } - virtual - ~CommandObjectTargetModules() + + ~CommandObjectTargetModules() override { } @@ -4406,12 +4388,11 @@ public: m_option_group.Finalize(); } - virtual - ~CommandObjectTargetSymbolsAdd () + ~CommandObjectTargetSymbolsAdd () override { } - virtual int + int HandleArgumentCompletion (Args &input, int &cursor_index, int &cursor_char_position, @@ -4419,7 +4400,7 @@ public: int match_start_point, int max_return_elements, bool &word_complete, - StringList &matches) + StringList &matches) override { std::string completion_str (input.GetArgumentAtIndex(cursor_index)); completion_str.erase (cursor_char_position); @@ -4435,8 +4416,8 @@ public: return matches.GetSize(); } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } @@ -4614,9 +4595,8 @@ protected: return false; } - virtual bool - DoExecute (Args& args, - CommandReturnObject &result) + bool + DoExecute (Args& args, CommandReturnObject &result) override { Target *target = m_exe_ctx.GetTargetPtr(); result.SetStatus (eReturnStatusFailed); @@ -4834,8 +4814,8 @@ public: LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetSymbolsAdd (interpreter))); } - virtual - ~CommandObjectTargetSymbols() + + ~CommandObjectTargetSymbols() override { } @@ -4874,16 +4854,16 @@ public: { } - ~CommandOptions () {} + ~CommandOptions () override {} const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -4970,7 +4950,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_class_name.clear(); m_function_name.clear(); @@ -5015,7 +4995,7 @@ public: }; Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -5030,13 +5010,13 @@ public: { } - ~CommandObjectTargetStopHookAdd () + ~CommandObjectTargetStopHookAdd () override { } protected: - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -5046,8 +5026,8 @@ protected: } } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override { if (m_stop_hook_sp) { @@ -5079,7 +5059,7 @@ protected: } bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { m_stop_hook_sp.reset(); @@ -5227,13 +5207,13 @@ public: { } - ~CommandObjectTargetStopHookDelete () + ~CommandObjectTargetStopHookDelete () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (target) @@ -5303,13 +5283,13 @@ public: { } - ~CommandObjectTargetStopHookEnableDisable () + ~CommandObjectTargetStopHookEnableDisable () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (target) @@ -5373,13 +5353,13 @@ public: { } - ~CommandObjectTargetStopHookList () + ~CommandObjectTargetStopHookList () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = GetSelectedOrDummyTarget(); if (!target) @@ -5439,7 +5419,7 @@ public: LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter))); } - ~CommandObjectMultiwordTargetStopHooks() + ~CommandObjectMultiwordTargetStopHooks() override { } }; diff --git a/source/Commands/CommandObjectTarget.h b/source/Commands/CommandObjectTarget.h index 7b6637812c4c..d99a2b07f9a7 100644 --- a/source/Commands/CommandObjectTarget.h +++ b/source/Commands/CommandObjectTarget.h @@ -30,12 +30,9 @@ public: CommandObjectMultiwordTarget (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordTarget (); - - + ~CommandObjectMultiwordTarget() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectTarget_h_ +#endif // liblldb_CommandObjectTarget_h_ diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index 5f38ad4900d6..e932c9d96c35 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -58,9 +58,10 @@ public: { } - virtual ~CommandObjectIterateOverThreads() {} - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + ~CommandObjectIterateOverThreads() override {} + + bool + DoExecute (Args& command, CommandReturnObject &result) override { result.SetStatus (m_success_return); @@ -162,13 +163,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -211,7 +211,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_count = UINT32_MAX; m_start = 0; @@ -219,7 +219,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -248,12 +248,12 @@ public: { } - ~CommandObjectThreadBacktrace() + ~CommandObjectThreadBacktrace() override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -285,8 +285,8 @@ protected: } } - virtual bool - HandleOneThread (Thread &thread, CommandReturnObject &result) + bool + HandleOneThread (Thread &thread, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); @@ -343,13 +343,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -426,7 +425,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_step_in_avoid_no_debug = eLazyBoolCalculate; m_step_out_avoid_no_debug = eLazyBoolCalculate; @@ -444,7 +443,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -493,21 +492,19 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectThreadStepWithTypeAndScope () + ~CommandObjectThreadStepWithTypeAndScope () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); bool synchronous_execution = m_interpreter.GetSynchronous(); @@ -589,7 +586,7 @@ protected: if (frame->HasDebugInformation ()) { new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans, - frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, + frame->GetSymbolContext(eSymbolContextEverything).line_entry, frame->GetSymbolContext(eSymbolContextEverything), m_options.m_step_in_target.c_str(), stop_other_threads, @@ -612,7 +609,7 @@ protected: if (frame->HasDebugInformation()) new_plan_sp = thread->QueueThreadPlanForStepOverRange (abort_other_plans, - frame->GetSymbolContext(eSymbolContextEverything).line_entry.range, + frame->GetSymbolContext(eSymbolContextEverything).line_entry, frame->GetSymbolContext(eSymbolContextEverything), stop_other_threads, m_options.m_step_out_avoid_no_debug); @@ -780,13 +777,12 @@ public: } - virtual - ~CommandObjectThreadContinue () + ~CommandObjectThreadContinue () override { } - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous (); @@ -980,13 +976,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1042,7 +1037,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_thread_idx = LLDB_INVALID_THREAD_ID; m_frame_idx = 0; @@ -1051,7 +1046,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1093,21 +1088,19 @@ public: } - virtual - ~CommandObjectThreadUntil () + ~CommandObjectThreadUntil () override { } - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous (); @@ -1371,14 +1364,13 @@ public: } - virtual - ~CommandObjectThreadSelect () + ~CommandObjectThreadSelect () override { } protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == NULL) @@ -1434,13 +1426,13 @@ public: { } - ~CommandObjectThreadList() + ~CommandObjectThreadList() override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1492,19 +1484,18 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_json_thread = false; m_json_stopinfo = false; } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { const int short_option = m_getopt_table[option_idx].val; Error error; @@ -1527,7 +1518,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1538,21 +1529,18 @@ public: static OptionDefinition g_option_table[]; }; - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } - - virtual - ~CommandObjectThreadInfo () + ~CommandObjectThreadInfo () override { } - virtual bool - HandleOneThread (Thread &thread, CommandReturnObject &result) + bool + HandleOneThread (Thread &thread, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); if (!thread.GetDescription (strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) @@ -1597,13 +1585,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1631,13 +1618,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_from_expression = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1651,9 +1638,8 @@ public: // Instance variables to hold the values for command options. }; - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -1686,17 +1672,14 @@ public: } - ~CommandObjectThreadReturn() + ~CommandObjectThreadReturn() override { } protected: - bool DoExecute - ( - const char *command, - CommandReturnObject &result - ) + bool + DoExecute (const char *command, CommandReturnObject &result) override { // I am going to handle this by hand, because I don't want you to have to say: // "thread return -- -5". @@ -1810,7 +1793,7 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_filenames.Clear(); m_line_num = 0; @@ -1819,13 +1802,12 @@ public: m_force = false; } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { bool success; const int short_option = m_getopt_table[option_idx].val; @@ -1866,7 +1848,7 @@ public: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1880,9 +1862,8 @@ public: static OptionDefinition g_option_table[]; }; - virtual Options * - GetOptions () + GetOptions () override { return &m_options; } @@ -1900,13 +1881,13 @@ public: { } - ~CommandObjectThreadJump() + ~CommandObjectThreadJump() override { } protected: - bool DoExecute (Args& args, CommandReturnObject &result) + bool DoExecute (Args& args, CommandReturnObject &result) override { RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); StackFrame *frame = m_exe_ctx.GetFramePtr(); @@ -2017,13 +1998,12 @@ public: OptionParsingStarting (); } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -2049,14 +2029,14 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_verbose = false; m_internal = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -2085,19 +2065,19 @@ public: { } - ~CommandObjectThreadPlanList () + ~CommandObjectThreadPlanList () override { } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } protected: - virtual bool - HandleOneThread (Thread &thread, CommandReturnObject &result) + bool + HandleOneThread (Thread &thread, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); DescriptionLevel desc_level = eDescriptionLevelFull; @@ -2148,10 +2128,10 @@ public: m_arguments.push_back (arg); } - virtual ~CommandObjectThreadPlanDiscard () {} + ~CommandObjectThreadPlanDiscard () override {} bool - DoExecute (Args& args, CommandReturnObject &result) + DoExecute (Args& args, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); if (args.GetArgumentCount() != 1) @@ -2211,7 +2191,7 @@ public: LoadSubCommand ("discard", CommandObjectSP (new CommandObjectThreadPlanDiscard (interpreter))); } - virtual ~CommandObjectMultiwordThreadPlan () {} + ~CommandObjectMultiwordThreadPlan () override {} }; diff --git a/source/Commands/CommandObjectThread.h b/source/Commands/CommandObjectThread.h index 52902ee36c76..90f8236b4428 100644 --- a/source/Commands/CommandObjectThread.h +++ b/source/Commands/CommandObjectThread.h @@ -24,11 +24,9 @@ public: CommandObjectMultiwordThread (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordThread (); - + ~CommandObjectMultiwordThread() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectThread_h_ +#endif // liblldb_CommandObjectThread_h_ diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp index 584e94d0452d..b57ac70f8f1a 100644 --- a/source/Commands/CommandObjectType.cpp +++ b/source/Commands/CommandObjectType.cpp @@ -30,6 +30,10 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueLanguage.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" @@ -144,17 +148,16 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg); + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting (); + OptionParsingStarting () override; const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -177,8 +180,8 @@ private: CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -200,12 +203,12 @@ public: CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); - ~CommandObjectTypeSummaryAdd () + ~CommandObjectTypeSummaryAdd () override { } - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" "def function (valobj,internal_dict):\n" @@ -221,8 +224,8 @@ public: } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); @@ -353,7 +356,7 @@ public: Error* error = NULL); protected: bool - DoExecute (Args& command, CommandReturnObject &result); + DoExecute (Args& command, CommandReturnObject &result) override; }; @@ -383,11 +386,10 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -428,7 +430,7 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { m_cascade = true; m_class_name = ""; @@ -441,7 +443,7 @@ private: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -469,8 +471,8 @@ private: CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -483,7 +485,7 @@ private: protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { WarnOnPotentialUnquotedUnsignedType(command, result); @@ -499,8 +501,8 @@ protected: } } - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -511,8 +513,8 @@ protected: } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &data) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); @@ -626,7 +628,7 @@ public: CommandObjectTypeSynthAdd (CommandInterpreter &interpreter); - ~CommandObjectTypeSynthAdd () + ~CommandObjectTypeSynthAdd () override { } @@ -656,22 +658,21 @@ private: { } - virtual - ~CommandOptions () + ~CommandOptions () override { } - virtual uint32_t - GetNumDefinitions (); + uint32_t + GetNumDefinitions () override; - virtual const OptionDefinition* - GetDefinitions () + const OptionDefinition* + GetDefinitions () override { return g_option_table; } - virtual void - OptionParsingStarting (CommandInterpreter &interpreter) + void + OptionParsingStarting (CommandInterpreter &interpreter) override { m_cascade = true; m_skip_pointers = false; @@ -680,10 +681,10 @@ private: m_category.assign("default"); m_custom_type_name.clear(); } - virtual Error + Error SetOptionValue (CommandInterpreter &interpreter, uint32_t option_idx, - const char *option_value) + const char *option_value) override { Error error; const int short_option = g_option_table[option_idx].short_option; @@ -737,8 +738,8 @@ private: OptionGroupFormat m_format_options; CommandOptions m_command_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } @@ -806,13 +807,13 @@ pointers to floats. Nor will it change the default display for Afloat and Bfloa } - ~CommandObjectTypeFormatAdd () + ~CommandObjectTypeFormatAdd () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -906,14 +907,9 @@ CommandObjectTypeFormatAdd::CommandOptions::GetNumDefinitions () return sizeof(g_option_table) / sizeof (OptionDefinition); } - -//------------------------------------------------------------------------- -// CommandObjectTypeFormatDelete -//------------------------------------------------------------------------- - -class CommandObjectTypeFormatDelete : public CommandObjectParsed +class CommandObjectTypeFormatterDelete : public CommandObjectParsed { -private: +protected: class CommandOptions : public Options { public: @@ -923,11 +919,10 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -940,6 +935,9 @@ private: case 'w': m_category = std::string(option_arg); break; + case 'l': + m_language = Language::GetLanguageTypeFromString(option_arg); + break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); break; @@ -949,14 +947,15 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { m_delete_all = false; m_category = "default"; + m_language = lldb::eLanguageTypeUnknown; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -969,33 +968,29 @@ private: bool m_delete_all; std::string m_category; - + lldb::LanguageType m_language; }; CommandOptions m_options; + uint32_t m_formatter_kind_mask; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& category_sp) - { - ConstString *name = (ConstString*)param; - category_sp->Delete(*name, eFormatCategoryItemValue | eFormatCategoryItemRegexValue); - return true; - } - public: - CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type format delete", - "Delete an existing formatting style for a type.", - NULL), - m_options(interpreter) + CommandObjectTypeFormatterDelete (CommandInterpreter &interpreter, + uint32_t formatter_kind_mask, + const char* name, + const char* help) : + CommandObjectParsed (interpreter, + name, + help, + NULL), + m_options(interpreter), + m_formatter_kind_mask(formatter_kind_mask) { CommandArgumentEntry type_arg; CommandArgumentData type_style_arg; @@ -1009,13 +1004,17 @@ public: } - ~CommandObjectTypeFormatDelete () + ~CommandObjectTypeFormatterDelete () override = default; + +protected: + virtual bool + FormatterSpecificDeletion (ConstString typeCS) { + return false; } -protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -1038,25 +1037,42 @@ protected: if (m_options.m_delete_all) { - DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS); + DataVisualization::Categories::ForEach( [this, typeCS] (const lldb::TypeCategoryImplSP& category_sp) -> bool { + category_sp->Delete(typeCS, m_formatter_kind_mask); + return true; + }); result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); + bool delete_category = false; + bool extra_deletion = false; - bool delete_category = category->Delete(typeCS, - eFormatCategoryItemValue | eFormatCategoryItemRegexValue); + if (m_options.m_language != lldb::eLanguageTypeUnknown) + { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(m_options.m_language, category); + if (category) + delete_category = category->Delete(typeCS, m_formatter_kind_mask); + extra_deletion = FormatterSpecificDeletion(typeCS); + } + else + { + lldb::TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); + if (category) + delete_category = category->Delete(typeCS, m_formatter_kind_mask); + extra_deletion = FormatterSpecificDeletion(typeCS); + } - if (delete_category) + if (delete_category || extra_deletion) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } else { - result.AppendErrorWithFormat ("no custom format for %s.\n", typeA); + result.AppendErrorWithFormat ("no custom formatter for %s.\n", typeA); result.SetStatus(eReturnStatusFailed); return false; } @@ -1066,18 +1082,15 @@ protected: }; OptionDefinition -CommandObjectTypeFormatDelete::CommandOptions::g_option_table[] = +CommandObjectTypeFormatterDelete::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, + { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Delete from given language's category."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; -//------------------------------------------------------------------------- -// CommandObjectTypeFormatClear -//------------------------------------------------------------------------- - -class CommandObjectTypeFormatClear : public CommandObjectParsed +class CommandObjectTypeFormatterClear : public CommandObjectParsed { private: @@ -1090,11 +1103,10 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1113,13 +1125,13 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { m_delete_all = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1129,50 +1141,52 @@ private: static OptionDefinition g_option_table[]; // Instance variables to hold the values for command options. - bool m_delete_all; - bool m_delete_named; }; CommandOptions m_options; - - virtual Options * - GetOptions () + uint32_t m_formatter_kind_mask; + + Options * + GetOptions () override { return &m_options; } - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) +public: + CommandObjectTypeFormatterClear (CommandInterpreter &interpreter, + uint32_t formatter_kind_mask, + const char* name, + const char* help) : + CommandObjectParsed (interpreter, + name, + help, + NULL), + m_options(interpreter), + m_formatter_kind_mask(formatter_kind_mask) { - cate->GetTypeFormatsContainer()->Clear(); - cate->GetRegexTypeFormatsContainer()->Clear(); - return true; - } -public: - CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type format clear", - "Delete all existing format styles.", - NULL), - m_options(interpreter) + ~CommandObjectTypeFormatterClear () override { } - ~CommandObjectTypeFormatClear () +protected: + virtual void + FormatterSpecificDeletion () { } -protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { if (m_options.m_delete_all) - DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); - + { + DataVisualization::Categories::ForEach( [this] (const TypeCategoryImplSP& category_sp) -> bool { + category_sp->Clear(m_formatter_kind_mask); + return true; + }); + } else { lldb::TypeCategoryImplSP category; @@ -1183,10 +1197,14 @@ protected: DataVisualization::Categories::GetCategory(cat_nameCS, category); } else + { DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->Clear(eFormatCategoryItemValue | eFormatCategoryItemRegexValue); + } + category->Clear(m_formatter_kind_mask); } + FormatterSpecificDeletion(); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } @@ -1194,46 +1212,68 @@ protected: }; OptionDefinition -CommandObjectTypeFormatClear::CommandOptions::g_option_table[] = +CommandObjectTypeFormatterClear::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; //------------------------------------------------------------------------- -// CommandObjectTypeFormatList +// CommandObjectTypeFormatDelete //------------------------------------------------------------------------- -bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); -bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry); +class CommandObjectTypeFormatDelete : public CommandObjectTypeFormatterDelete +{ +public: + CommandObjectTypeFormatDelete (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterDelete (interpreter, + eFormatCategoryItemValue | eFormatCategoryItemRegexValue, + "type format delete", + "Delete an existing formatting style for a type.") + { + } + + ~CommandObjectTypeFormatDelete () override + { + } +}; -class CommandObjectTypeFormatList; +//------------------------------------------------------------------------- +// CommandObjectTypeFormatClear +//------------------------------------------------------------------------- -struct CommandObjectTypeFormatList_LoopCallbackParam { - CommandObjectTypeFormatList* self; - CommandReturnObject* result; - RegularExpression* regex; - RegularExpression* cate_regex; - CommandObjectTypeFormatList_LoopCallbackParam(CommandObjectTypeFormatList* S, CommandReturnObject* R, - RegularExpression* X = NULL, RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} +class CommandObjectTypeFormatClear : public CommandObjectTypeFormatterClear +{ +public: + CommandObjectTypeFormatClear (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterClear (interpreter, + eFormatCategoryItemValue | eFormatCategoryItemRegexValue, + "type format clear", + "Delete all existing format styles.") + { + } }; -class CommandObjectTypeFormatList : public CommandObjectParsed +template +class CommandObjectTypeFormatterList : public CommandObjectParsed { + typedef typename FormatterType::SharedPointer FormatterSharedPointer; + class CommandOptions : public Options { public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter), + m_category_regex("",""), + m_category_language(lldb::eLanguageTypeUnknown, lldb::eLanguageTypeUnknown) { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -1241,7 +1281,10 @@ class CommandObjectTypeFormatList : public CommandObjectParsed switch (short_option) { case 'w': - m_category_regex = std::string(option_arg); + m_category_regex.SetCurrentValue(option_arg); + break; + case 'l': + error = m_category_language.SetValueFromString(option_arg); break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); @@ -1252,14 +1295,22 @@ class CommandObjectTypeFormatList : public CommandObjectParsed } void - OptionParsingStarting () + OptionParsingStarting () override { - m_category_regex = ""; + m_category_regex.Clear(); + m_category_language.Clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { + static OptionDefinition g_option_table[] = + { + { LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, + { LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Only show the category for a specific language."}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } + }; + return g_option_table; } @@ -1269,23 +1320,25 @@ class CommandObjectTypeFormatList : public CommandObjectParsed // Instance variables to hold the values for command options. - std::string m_category_regex; - + OptionValueString m_category_regex; + OptionValueLanguage m_category_language; }; CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } public: - CommandObjectTypeFormatList (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterList (CommandInterpreter &interpreter, + const char* name, + const char* help) : CommandObjectParsed (interpreter, - "type format list", - "Show a list of current formatting styles.", + name, + help, NULL), m_options(interpreter) { @@ -1300,117 +1353,155 @@ public: m_arguments.push_back (type_arg); } - ~CommandObjectTypeFormatList () + ~CommandObjectTypeFormatterList () override { } protected: + virtual void + FormatterSpecificList (CommandReturnObject &result) + { + } + bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); - CommandObjectTypeFormatList_LoopCallbackParam *param; - RegularExpression* cate_regex = - m_options.m_category_regex.empty() ? NULL : - new RegularExpression(m_options.m_category_regex.c_str()); + std::unique_ptr category_regex; + std::unique_ptr formatter_regex; - if (argc == 1) + if (m_options.m_category_regex.OptionWasSet()) { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,regex,cate_regex); + category_regex.reset(new RegularExpression()); + if (!category_regex->Compile(m_options.m_category_regex.GetCurrentValue())) + { + result.AppendErrorWithFormat("syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValue()); + result.SetStatus(eReturnStatusFailed); + return false; + } } - else - param = new CommandObjectTypeFormatList_LoopCallbackParam(this,&result,NULL,cate_regex); - - DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - delete param; - - if (cate_regex) - delete cate_regex; - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -private: - - static bool - PerCategoryCallback(void* param_vp, - const lldb::TypeCategoryImplSP& cate) - { - - CommandObjectTypeFormatList_LoopCallbackParam* param = - (CommandObjectTypeFormatList_LoopCallbackParam*)param_vp; - CommandReturnObject* result = param->result; - - const char* cate_name = cate->GetName(); - - // if the category is disabled or empty and there is no regex, just skip it - if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemValue | eFormatCategoryItemRegexValue) == 0) && param->cate_regex == NULL) - return true; - // if we have a regex and this category does not match it, just skip it - if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) - return true; - - result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", - cate_name, - (cate->IsEnabled() ? "enabled" : "disabled")); + if (argc == 1) + { + const char* arg = command.GetArgumentAtIndex(1); + formatter_regex.reset(new RegularExpression()); + if (!formatter_regex->Compile(arg)) + { + result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); + result.SetStatus(eReturnStatusFailed); + return false; + } + } - cate->GetTypeFormatsContainer()->LoopThrough(CommandObjectTypeFormatList_LoopCallback, param_vp); + auto category_closure = [&result, &formatter_regex] (const lldb::TypeCategoryImplSP& category) -> void { + result.GetOutputStream().Printf("-----------------------\nCategory: %s\n-----------------------\n", category->GetName()); + + typedef const std::shared_ptr Bar; + typedef std::function Func1Type; + typedef std::function Func2Type; + + TypeCategoryImpl::ForEachCallbacks foreach; + foreach.SetExact([&result, &formatter_regex] (ConstString name, const FormatterSharedPointer& format_sp) -> bool { + if (formatter_regex) + { + bool escape = true; + if (0 == strcmp(name.AsCString(), formatter_regex->GetText())) + { + escape = false; + } + else if (formatter_regex->Execute(name.AsCString())) + { + escape = false; + } + + if (escape) + return true; + } + + result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), format_sp->GetDescription().c_str()); + + return true; + }); + + foreach.SetWithRegex( [&result, &formatter_regex] (RegularExpressionSP regex_sp, const FormatterSharedPointer& format_sp) -> bool { + if (formatter_regex) + { + bool escape = true; + if (0 == strcmp(regex_sp->GetText(), formatter_regex->GetText())) + { + escape = false; + } + else if (formatter_regex->Execute(regex_sp->GetText())) + { + escape = false; + } + + if (escape) + return true; + } + + result.GetOutputStream().Printf ("%s: %s\n", regex_sp->GetText(), format_sp->GetDescription().c_str()); + + return true; + }); + + category->ForEach(foreach); + }; - if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) + if (m_options.m_category_language.OptionWasSet()) { - result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); - cate->GetRegexTypeFormatsContainer()->LoopThrough(CommandObjectTypeRXFormatList_LoopCallback, param_vp); + lldb::TypeCategoryImplSP category_sp; + DataVisualization::Categories::GetCategory(m_options.m_category_language.GetCurrentValue(), category_sp); + if (category_sp) + category_closure(category_sp); } - return true; - } - - - bool - LoopCallback (const char* type, - const lldb::TypeFormatImplSP& entry, - RegularExpression* regex, - CommandReturnObject *result) - { - if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type)) - result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); - return true; + else + { + DataVisualization::Categories::ForEach( [this, &command, &result, &category_regex, &formatter_regex, &category_closure] (const lldb::TypeCategoryImplSP& category) -> bool { + if (category_regex) + { + bool escape = true; + if (0 == strcmp(category->GetName(), category_regex->GetText())) + { + escape = false; + } + else if (category_regex->Execute(category->GetName())) + { + escape = false; + } + + if (escape) + return true; + } + + category_closure(category); + + return true; + }); + + FormatterSpecificList(result); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); } - - friend bool CommandObjectTypeFormatList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeFormatImplSP& entry); - friend bool CommandObjectTypeRXFormatList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeFormatImplSP& entry); - }; -bool -CommandObjectTypeFormatList_LoopCallback ( - void* pt2self, - ConstString type, - const lldb::TypeFormatImplSP& entry) -{ - CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); -} - -bool -CommandObjectTypeRXFormatList_LoopCallback ( - void* pt2self, - lldb::RegularExpressionSP regex, - const lldb::TypeFormatImplSP& entry) -{ - CommandObjectTypeFormatList_LoopCallbackParam* param = (CommandObjectTypeFormatList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); -} +//------------------------------------------------------------------------- +// CommandObjectTypeFormatList +//------------------------------------------------------------------------- -OptionDefinition -CommandObjectTypeFormatList::CommandOptions::g_option_table[] = +class CommandObjectTypeFormatList : public CommandObjectTypeFormatterList { - { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +public: + + CommandObjectTypeFormatList (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterList(interpreter, + "type format list", + "Show a list of current formats.") + { + } }; #ifndef LLDB_DISABLE_PYTHON @@ -1438,6 +1529,9 @@ CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx case 'e': m_flags.SetDontShowChildren(false); break; + case 'h': + m_flags.SetHideEmptyAggregates(true); + break; case 'v': m_flags.SetDontShowValue(true); break; @@ -1924,6 +2018,7 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."}, { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Do not expand aggregate data types with no children."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "A name for this summary string."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -1933,34 +2028,113 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = // CommandObjectTypeSummaryDelete //------------------------------------------------------------------------- -class CommandObjectTypeSummaryDelete : public CommandObjectParsed +class CommandObjectTypeSummaryDelete : public CommandObjectTypeFormatterDelete { -private: +public: + CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterDelete (interpreter, + eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, + "type summary delete", + "Delete an existing summary for a type.") + { + } + + ~CommandObjectTypeSummaryDelete () override + { + } + +protected: + bool + FormatterSpecificDeletion (ConstString typeCS) override + { + if (m_options.m_language != lldb::eLanguageTypeUnknown) + return false; + return DataVisualization::NamedSummaryFormats::Delete(typeCS); + } +}; + +class CommandObjectTypeSummaryClear : public CommandObjectTypeFormatterClear +{ +public: + CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterClear (interpreter, + eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary, + "type summary clear", + "Delete all existing summaries.") + { + } + +protected: + void + FormatterSpecificDeletion () override + { + DataVisualization::NamedSummaryFormats::Clear(); + } +}; + +//------------------------------------------------------------------------- +// CommandObjectTypeSummaryList +//------------------------------------------------------------------------- + +class CommandObjectTypeSummaryList : public CommandObjectTypeFormatterList +{ +public: + + CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterList(interpreter, + "type summary list", + "Show a list of current summaries.") + { + } + +protected: + void + FormatterSpecificList (CommandReturnObject &result) override + { + if (DataVisualization::NamedSummaryFormats::GetCount() > 0) + { + result.GetOutputStream().Printf("Named summaries:\n"); + DataVisualization::NamedSummaryFormats::ForEach( [&result] (ConstString name, const TypeSummaryImplSP& summary_sp) -> bool { + result.GetOutputStream().Printf ("%s: %s\n", name.AsCString(), summary_sp->GetDescription().c_str()); + return true; + }); + } + } +}; + +//------------------------------------------------------------------------- +// CommandObjectTypeCategoryDefine +//------------------------------------------------------------------------- + +class CommandObjectTypeCategoryDefine : public CommandObjectParsed +{ + class CommandOptions : public Options { public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter), + m_define_enabled(false,false), + m_cate_language(eLanguageTypeUnknown,eLanguageTypeUnknown) { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'a': - m_delete_all = true; + case 'e': + m_define_enabled.SetValueFromString("true"); break; - case 'w': - m_category = std::string(option_arg); + case 'l': + error = m_cate_language.SetValueFromString(option_arg); break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); @@ -1971,14 +2145,14 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { - m_delete_all = false; - m_category = "default"; + m_define_enabled.Clear(); + m_cate_language.Clear(); } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -1989,41 +2163,33 @@ private: // Instance variables to hold the values for command options. - bool m_delete_all; - std::string m_category; + OptionValueBoolean m_define_enabled; + OptionValueLanguage m_cate_language; + }; CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& category_sp) - { - ConstString *name = (ConstString*)param; - category_sp->Delete(*name, eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); - return true; - } public: - CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type summary delete", - "Delete an existing summary style for a type.", - NULL), - m_options(interpreter) + CommandObjectTypeCategoryDefine (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "type category define", + "Define a new category as a source of formatters.", + NULL), + m_options(interpreter) { CommandArgumentEntry type_arg; CommandArgumentData type_style_arg; type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; + type_style_arg.arg_repetition = eArgRepeatPlus; type_arg.push_back (type_style_arg); @@ -2031,74 +2197,55 @@ public: } - ~CommandObjectTypeSummaryDelete () + ~CommandObjectTypeCategoryDefine () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); - if (argc != 1) - { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) + if (argc < 1) { - result.AppendError("empty typenames not allowed"); + result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } - if (m_options.m_delete_all) - { - DataVisualization::Categories::LoopThrough(PerCategoryCallback, &typeCS); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - - bool delete_category = category->Delete(typeCS, - eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); - bool delete_named = DataVisualization::NamedSummaryFormats::Delete(typeCS); - - if (delete_category || delete_named) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - else + for (size_t i = 0; i < argc; i++) { - result.AppendErrorWithFormat ("no custom summary for %s.\n", typeA); - result.SetStatus(eReturnStatusFailed); - return false; + const char* cateName = command.GetArgumentAtIndex(i); + TypeCategoryImplSP category_sp; + if (DataVisualization::Categories::GetCategory(ConstString(cateName), category_sp) && category_sp) + { + category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); + if (m_options.m_define_enabled.GetCurrentValue()) + DataVisualization::Categories::Enable(category_sp, TypeCategoryMap::Default); + } } + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); } + }; OptionDefinition -CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = +CommandObjectTypeCategoryDefine::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, - { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, + { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "If specified, this category will be created enabled."}, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Specify the language that this category is supported for."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; -class CommandObjectTypeSummaryClear : public CommandObjectParsed +//------------------------------------------------------------------------- +// CommandObjectTypeCategoryEnable +//------------------------------------------------------------------------- + +class CommandObjectTypeCategoryEnable : public CommandObjectParsed { -private: - class CommandOptions : public Options { public: @@ -2108,19 +2255,23 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'a': - m_delete_all = true; + case 'l': + if (option_arg) + { + m_language = Language::GetLanguageTypeFromString(option_arg); + if (m_language == lldb::eLanguageTypeUnknown) + error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); + } break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); @@ -2131,13 +2282,13 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { - m_delete_all = false; + m_language = lldb::eLanguageTypeUnknown; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -2148,65 +2299,87 @@ private: // Instance variables to hold the values for command options. - bool m_delete_all; - bool m_delete_named; + lldb::LanguageType m_language; + }; CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) - { - cate->GetTypeSummariesContainer()->Clear(); - cate->GetRegexTypeSummariesContainer()->Clear(); - return true; - - } - public: - CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : + CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, - "type summary clear", - "Delete all existing summary styles.", + "type category enable", + "Enable a category as a source of formatters.", NULL), m_options(interpreter) { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back (type_style_arg); + + m_arguments.push_back (type_arg); + } - ~CommandObjectTypeSummaryClear () + ~CommandObjectTypeCategoryEnable () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { + const size_t argc = command.GetArgumentCount(); - if (m_options.m_delete_all) - DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); + if (argc < 1 && + m_options.m_language == lldb::eLanguageTypeUnknown) + { + result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } - else - { - lldb::TypeCategoryImplSP category; - if (command.GetArgumentCount() > 0) + if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) + { + DataVisualization::Categories::EnableStar(); + } + else if (argc > 0) + { + for (int i = argc - 1; i >= 0; i--) { - const char* cat_name = command.GetArgumentAtIndex(0); - ConstString cat_nameCS(cat_name); - DataVisualization::Categories::GetCategory(cat_nameCS, category); + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + DataVisualization::Categories::Enable(typeCS); + lldb::TypeCategoryImplSP cate; + if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get()) + { + if (cate->GetCount() == 0) + { + result.AppendWarning("empty category enabled (typo?)"); + } + } } - else - DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); } - DataVisualization::NamedSummaryFormats::Clear(); + if (m_options.m_language != lldb::eLanguageTypeUnknown) + DataVisualization::Categories::Enable(m_options.m_language); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); @@ -2215,34 +2388,91 @@ protected: }; OptionDefinition -CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = +CommandObjectTypeCategoryEnable::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; //------------------------------------------------------------------------- -// CommandObjectTypeSummaryList +// CommandObjectTypeCategoryDelete //------------------------------------------------------------------------- -bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const StringSummaryFormat::SharedPointer& entry); -bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); - -class CommandObjectTypeSummaryList; - -struct CommandObjectTypeSummaryList_LoopCallbackParam { - CommandObjectTypeSummaryList* self; - CommandReturnObject* result; - RegularExpression* regex; - RegularExpression* cate_regex; - CommandObjectTypeSummaryList_LoopCallbackParam(CommandObjectTypeSummaryList* S, CommandReturnObject* R, - RegularExpression* X = NULL, - RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} +class CommandObjectTypeCategoryDelete : public CommandObjectParsed +{ +public: + CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "type category delete", + "Delete a category and all associated formatters.", + NULL) + { + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back (type_style_arg); + + m_arguments.push_back (type_arg); + + } + + ~CommandObjectTypeCategoryDelete () override + { + } + +protected: + bool + DoExecute (Args& command, CommandReturnObject &result) override + { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) + { + result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + bool success = true; + + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) + { + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + if (!DataVisualization::Categories::Delete(typeCS)) + success = false; // keep deleting even if we hit an error + } + if (success) + { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } + else + { + result.AppendError("cannot delete one or more categories\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } }; -class CommandObjectTypeSummaryList : public CommandObjectParsed +//------------------------------------------------------------------------- +// CommandObjectTypeCategoryDisable +//------------------------------------------------------------------------- + +class CommandObjectTypeCategoryDisable : public CommandObjectParsed { - class CommandOptions : public Options { public: @@ -2252,19 +2482,23 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'w': - m_category_regex = std::string(option_arg); + case 'l': + if (option_arg) + { + m_language = Language::GetLanguageTypeFromString(option_arg); + if (m_language == lldb::eLanguageTypeUnknown) + error.SetErrorStringWithFormat ("unrecognized language '%s'", option_arg); + } break; default: error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); @@ -2275,13 +2509,13 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed } void - OptionParsingStarting () + OptionParsingStarting () override { - m_category_regex = ""; + m_language = lldb::eLanguageTypeUnknown; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -2292,23 +2526,23 @@ class CommandObjectTypeSummaryList : public CommandObjectParsed // Instance variables to hold the values for command options. - std::string m_category_regex; + lldb::LanguageType m_language; }; CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - + public: - CommandObjectTypeSummaryList (CommandInterpreter &interpreter) : + CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, - "type summary list", - "Show a list of current summary styles.", + "type category disable", + "Disable a category as a source of formatters.", NULL), m_options(interpreter) { @@ -2316,399 +2550,76 @@ public: CommandArgumentData type_style_arg; type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatOptional; + type_style_arg.arg_repetition = eArgRepeatPlus; type_arg.push_back (type_style_arg); m_arguments.push_back (type_arg); + } - ~CommandObjectTypeSummaryList () + ~CommandObjectTypeCategoryDisable () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); - CommandObjectTypeSummaryList_LoopCallbackParam *param; - RegularExpression* cate_regex = - m_options.m_category_regex.empty() ? NULL : - new RegularExpression(m_options.m_category_regex.c_str()); - - if (argc == 1) + if (argc < 1 && + m_options.m_language == lldb::eLanguageTypeUnknown) { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex,cate_regex); + result.AppendErrorWithFormat ("%s takes arguments and/or a language", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - else - param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,NULL,cate_regex); - DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - delete param; - - if (DataVisualization::NamedSummaryFormats::GetCount() > 0) + if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) { - result.GetOutputStream().Printf("Named summaries:\n"); - if (argc == 1) + DataVisualization::Categories::DisableStar(); + } + else if (argc > 0) + { + // the order is not relevant here + for (int i = argc - 1; i >= 0; i--) { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); + const char* typeA = command.GetArgumentAtIndex(i); + ConstString typeCS(typeA); + + if (!typeCS) + { + result.AppendError("empty category name not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + DataVisualization::Categories::Disable(typeCS); } - else - param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); - DataVisualization::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); - delete param; } - if (cate_regex) - delete cate_regex; - + if (m_options.m_language != lldb::eLanguageTypeUnknown) + DataVisualization::Categories::Disable(m_options.m_language); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } -private: - - static bool - PerCategoryCallback(void* param_vp, - const lldb::TypeCategoryImplSP& cate) - { - - CommandObjectTypeSummaryList_LoopCallbackParam* param = - (CommandObjectTypeSummaryList_LoopCallbackParam*)param_vp; - CommandReturnObject* result = param->result; - - const char* cate_name = cate->GetName(); - - // if the category is disabled or empty and there is no regex, just skip it - if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary) == 0) && param->cate_regex == NULL) - return true; - - // if we have a regex and this category does not match it, just skip it - if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) - return true; - - result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", - cate_name, - (cate->IsEnabled() ? "enabled" : "disabled")); - - cate->GetTypeSummariesContainer()->LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param_vp); - - if (cate->GetRegexTypeSummariesContainer()->GetCount() > 0) - { - result->GetOutputStream().Printf("Regex-based summaries (slower):\n"); - cate->GetRegexTypeSummariesContainer()->LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, param_vp); - } - return true; - } - - - bool - LoopCallback (const char* type, - const lldb::TypeSummaryImplSP& entry, - RegularExpression* regex, - CommandReturnObject *result) - { - if (regex == NULL || strcmp(type,regex->GetText()) == 0 || regex->Execute(type)) - result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); - return true; - } - - friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, ConstString type, const lldb::TypeSummaryImplSP& entry); - friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const lldb::TypeSummaryImplSP& entry); }; -bool -CommandObjectTypeSummaryList_LoopCallback ( - void* pt2self, - ConstString type, - const lldb::TypeSummaryImplSP& entry) -{ - CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); -} - -bool -CommandObjectTypeRXSummaryList_LoopCallback ( - void* pt2self, - lldb::RegularExpressionSP regex, - const lldb::TypeSummaryImplSP& entry) -{ - CommandObjectTypeSummaryList_LoopCallbackParam* param = (CommandObjectTypeSummaryList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); -} - OptionDefinition -CommandObjectTypeSummaryList::CommandOptions::g_option_table[] = +CommandObjectTypeCategoryDisable::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Enable the category for this language."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; -//------------------------------------------------------------------------- -// CommandObjectTypeCategoryEnable -//------------------------------------------------------------------------- - -class CommandObjectTypeCategoryEnable : public CommandObjectParsed -{ -public: - CommandObjectTypeCategoryEnable (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type category enable", - "Enable a category as a source of formatters.", - NULL) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } - - ~CommandObjectTypeCategoryEnable () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) - { - DataVisualization::Categories::EnableStar(); - } - else - { - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - DataVisualization::Categories::Enable(typeCS); - lldb::TypeCategoryImplSP cate; - if (DataVisualization::Categories::GetCategory(typeCS, cate) && cate.get()) - { - if (cate->GetCount() == 0) - { - result.AppendWarning("empty category enabled (typo?)"); - } - } - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -}; - -//------------------------------------------------------------------------- -// CommandObjectTypeCategoryDelete -//------------------------------------------------------------------------- - -class CommandObjectTypeCategoryDelete : public CommandObjectParsed -{ -public: - CommandObjectTypeCategoryDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type category delete", - "Delete a category and all associated formatters.", - NULL) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } - - ~CommandObjectTypeCategoryDelete () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes 1 or more arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - bool success = true; - - // the order is not relevant here - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - if (!DataVisualization::Categories::Delete(typeCS)) - success = false; // keep deleting even if we hit an error - } - if (success) - { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - else - { - result.AppendError("cannot delete one or more categories\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } -}; - -//------------------------------------------------------------------------- -// CommandObjectTypeCategoryDisable -//------------------------------------------------------------------------- - -class CommandObjectTypeCategoryDisable : public CommandObjectParsed -{ -public: - CommandObjectTypeCategoryDisable (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type category disable", - "Disable a category as a source of formatters.", - NULL) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } - - ~CommandObjectTypeCategoryDisable () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) - { - result.AppendErrorWithFormat ("%s takes 1 or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (argc == 1 && strcmp(command.GetArgumentAtIndex(0),"*") == 0) - { - DataVisualization::Categories::DisableStar(); - } - else - { - // the order is not relevant here - for (int i = argc - 1; i >= 0; i--) - { - const char* typeA = command.GetArgumentAtIndex(i); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty category name not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - DataVisualization::Categories::Disable(typeCS); - } - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -}; - //------------------------------------------------------------------------- // CommandObjectTypeCategoryList //------------------------------------------------------------------------- class CommandObjectTypeCategoryList : public CommandObjectParsed { -private: - - struct CommandObjectTypeCategoryList_CallbackParam - { - CommandReturnObject* result; - RegularExpression* regex; - - CommandObjectTypeCategoryList_CallbackParam(CommandReturnObject* res, - RegularExpression* rex = NULL) : - result(res), - regex(rex) - { - } - - }; - - static bool - PerCategoryCallback(void* param_vp, - const lldb::TypeCategoryImplSP& cate) - { - CommandObjectTypeCategoryList_CallbackParam* param = - (CommandObjectTypeCategoryList_CallbackParam*)param_vp; - CommandReturnObject* result = param->result; - RegularExpression* regex = param->regex; - - const char* cate_name = cate->GetName(); - - if (regex == NULL || strcmp(cate_name, regex->GetText()) == 0 || regex->Execute(cate_name)) - result->GetOutputStream().Printf("Category %s is%s enabled\n", - cate_name, - (cate->IsEnabled() ? "" : " not")); - return true; - } public: CommandObjectTypeCategoryList (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, @@ -2727,1060 +2638,175 @@ public: m_arguments.push_back (type_arg); } - ~CommandObjectTypeCategoryList () + ~CommandObjectTypeCategoryList () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); - RegularExpression* regex = NULL; + + std::unique_ptr regex; - if (argc == 0) - ; - else if (argc == 1) - regex = new RegularExpression(command.GetArgumentAtIndex(0)); - else - { - result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - CommandObjectTypeCategoryList_CallbackParam param(&result, - regex); - - DataVisualization::Categories::LoopThrough(PerCategoryCallback, ¶m); - - if (regex) - delete regex; - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -}; - -//------------------------------------------------------------------------- -// CommandObjectTypeFilterList -//------------------------------------------------------------------------- - -bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); -bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); - -class CommandObjectTypeFilterList; - -struct CommandObjectTypeFilterList_LoopCallbackParam { - CommandObjectTypeFilterList* self; - CommandReturnObject* result; - RegularExpression* regex; - RegularExpression* cate_regex; - CommandObjectTypeFilterList_LoopCallbackParam(CommandObjectTypeFilterList* S, CommandReturnObject* R, - RegularExpression* X = NULL, - RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} -}; - -class CommandObjectTypeFilterList : public CommandObjectParsed -{ - - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'w': - m_category_regex = std::string(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () - { - m_category_regex = ""; - } - - const OptionDefinition* - GetDefinitions () - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - std::string m_category_regex; - - }; - - CommandOptions m_options; - - virtual Options * - GetOptions () - { - return &m_options; - } - -public: - CommandObjectTypeFilterList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type filter list", - "Show a list of current filters.", - NULL), - m_options(interpreter) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatOptional; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } - - ~CommandObjectTypeFilterList () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - CommandObjectTypeFilterList_LoopCallbackParam *param; - RegularExpression* cate_regex = - m_options.m_category_regex.empty() ? NULL : - new RegularExpression(m_options.m_category_regex.c_str()); - - if (argc == 1) - { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,regex,cate_regex); - } - else - param = new CommandObjectTypeFilterList_LoopCallbackParam(this,&result,NULL,cate_regex); - - DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - delete param; - - if (cate_regex) - delete cate_regex; - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -private: - - static bool - PerCategoryCallback(void* param_vp, - const lldb::TypeCategoryImplSP& cate) - { - - const char* cate_name = cate->GetName(); - - CommandObjectTypeFilterList_LoopCallbackParam* param = - (CommandObjectTypeFilterList_LoopCallbackParam*)param_vp; - CommandReturnObject* result = param->result; - - // if the category is disabled or empty and there is no regex, just skip it - if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter) == 0) && param->cate_regex == NULL) - return true; - - // if we have a regex and this category does not match it, just skip it - if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) - return true; - - result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", - cate_name, - (cate->IsEnabled() ? "enabled" : "disabled")); - - cate->GetTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterList_LoopCallback, param_vp); - - if (cate->GetRegexTypeFiltersContainer()->GetCount() > 0) - { - result->GetOutputStream().Printf("Regex-based filters (slower):\n"); - cate->GetRegexTypeFiltersContainer()->LoopThrough(CommandObjectTypeFilterRXList_LoopCallback, param_vp); - } - - return true; - } - - bool - LoopCallback (const char* type, - const SyntheticChildren::SharedPointer& entry, - RegularExpression* regex, - CommandReturnObject *result) - { - if (regex == NULL || regex->Execute(type)) - result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); - return true; - } - - friend bool CommandObjectTypeFilterList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); - friend bool CommandObjectTypeFilterRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); -}; - -bool -CommandObjectTypeFilterList_LoopCallback (void* pt2self, - ConstString type, - const SyntheticChildren::SharedPointer& entry) -{ - CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); -} - -bool -CommandObjectTypeFilterRXList_LoopCallback (void* pt2self, - lldb::RegularExpressionSP regex, - const SyntheticChildren::SharedPointer& entry) -{ - CommandObjectTypeFilterList_LoopCallbackParam* param = (CommandObjectTypeFilterList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); -} - - -OptionDefinition -CommandObjectTypeFilterList::CommandOptions::g_option_table[] = -{ - { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } -}; - -#ifndef LLDB_DISABLE_PYTHON - -//------------------------------------------------------------------------- -// CommandObjectTypeSynthList -//------------------------------------------------------------------------- - -bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); -bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); - -class CommandObjectTypeSynthList; - -struct CommandObjectTypeSynthList_LoopCallbackParam { - CommandObjectTypeSynthList* self; - CommandReturnObject* result; - RegularExpression* regex; - RegularExpression* cate_regex; - CommandObjectTypeSynthList_LoopCallbackParam(CommandObjectTypeSynthList* S, CommandReturnObject* R, - RegularExpression* X = NULL, - RegularExpression* CX = NULL) : self(S), result(R), regex(X), cate_regex(CX) {} -}; - -class CommandObjectTypeSynthList : public CommandObjectParsed -{ - - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'w': - m_category_regex = std::string(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () - { - m_category_regex = ""; - } - - const OptionDefinition* - GetDefinitions () - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - std::string m_category_regex; - - }; - - CommandOptions m_options; - - virtual Options * - GetOptions () - { - return &m_options; - } - -public: - CommandObjectTypeSynthList (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type synthetic list", - "Show a list of current synthetic providers.", - NULL), - m_options(interpreter) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatOptional; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - } - - ~CommandObjectTypeSynthList () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - CommandObjectTypeSynthList_LoopCallbackParam *param; - RegularExpression* cate_regex = - m_options.m_category_regex.empty() ? NULL : - new RegularExpression(m_options.m_category_regex.c_str()); - - if (argc == 1) - { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,regex,cate_regex); - } - else - param = new CommandObjectTypeSynthList_LoopCallbackParam(this,&result,NULL,cate_regex); - - DataVisualization::Categories::LoopThrough(PerCategoryCallback,param); - delete param; - - if (cate_regex) - delete cate_regex; - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -private: - - static bool - PerCategoryCallback(void* param_vp, - const lldb::TypeCategoryImplSP& cate) - { - - CommandObjectTypeSynthList_LoopCallbackParam* param = - (CommandObjectTypeSynthList_LoopCallbackParam*)param_vp; - CommandReturnObject* result = param->result; - - const char* cate_name = cate->GetName(); - - // if the category is disabled or empty and there is no regex, just skip it - if ((cate->IsEnabled() == false || cate->GetCount(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth) == 0) && param->cate_regex == NULL) - return true; - - // if we have a regex and this category does not match it, just skip it - if(param->cate_regex != NULL && strcmp(cate_name,param->cate_regex->GetText()) != 0 && param->cate_regex->Execute(cate_name) == false) - return true; - - result->GetOutputStream().Printf("-----------------------\nCategory: %s (%s)\n-----------------------\n", - cate_name, - (cate->IsEnabled() ? "enabled" : "disabled")); - - cate->GetTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthList_LoopCallback, param_vp); - - if (cate->GetRegexTypeSyntheticsContainer()->GetCount() > 0) - { - result->GetOutputStream().Printf("Regex-based synthetic providers (slower):\n"); - cate->GetRegexTypeSyntheticsContainer()->LoopThrough(CommandObjectTypeSynthRXList_LoopCallback, param_vp); - } - - return true; - } - - bool - LoopCallback (const char* type, - const SyntheticChildren::SharedPointer& entry, - RegularExpression* regex, - CommandReturnObject *result) - { - if (regex == NULL || regex->Execute(type)) - result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); - return true; - } - - friend bool CommandObjectTypeSynthList_LoopCallback(void* pt2self, ConstString type, const SyntheticChildren::SharedPointer& entry); - friend bool CommandObjectTypeSynthRXList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SyntheticChildren::SharedPointer& entry); -}; - -bool -CommandObjectTypeSynthList_LoopCallback (void* pt2self, - ConstString type, - const SyntheticChildren::SharedPointer& entry) -{ - CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(type.AsCString(), entry, param->regex, param->result); -} - -bool -CommandObjectTypeSynthRXList_LoopCallback (void* pt2self, - lldb::RegularExpressionSP regex, - const SyntheticChildren::SharedPointer& entry) -{ - CommandObjectTypeSynthList_LoopCallbackParam* param = (CommandObjectTypeSynthList_LoopCallbackParam*)pt2self; - return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); -} - - -OptionDefinition -CommandObjectTypeSynthList::CommandOptions::g_option_table[] = -{ - { LLDB_OPT_SET_ALL, false, "category-regex", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Only show categories matching this filter."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } -}; - -#endif // #ifndef LLDB_DISABLE_PYTHON -//------------------------------------------------------------------------- -// CommandObjectTypeFilterDelete -//------------------------------------------------------------------------- - -class CommandObjectTypeFilterDelete : public CommandObjectParsed -{ -private: - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () - { - m_delete_all = false; - m_category = "default"; - } - - const OptionDefinition* - GetDefinitions () - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_delete_all; - std::string m_category; - - }; - - CommandOptions m_options; - - virtual Options * - GetOptions () - { - return &m_options; - } - - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) - { - ConstString *name = (ConstString*)param; - return cate->Delete(*name, eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); - } - -public: - CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type filter delete", - "Delete an existing filter for a type.", - NULL), - m_options(interpreter) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } - - ~CommandObjectTypeFilterDelete () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_options.m_delete_all) - { - DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - - bool delete_category = category->GetTypeFiltersContainer()->Delete(typeCS); - delete_category = category->GetRegexTypeFiltersContainer()->Delete(typeCS) || delete_category; - - if (delete_category) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - else - { - result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); - result.SetStatus(eReturnStatusFailed); - return false; - } - - } -}; - -OptionDefinition -CommandObjectTypeFilterDelete::CommandOptions::g_option_table[] = -{ - { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, - { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } -}; - -#ifndef LLDB_DISABLE_PYTHON - -//------------------------------------------------------------------------- -// CommandObjectTypeSynthDelete -//------------------------------------------------------------------------- - -class CommandObjectTypeSynthDelete : public CommandObjectParsed -{ -private: - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - case 'w': - m_category = std::string(option_arg); - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () - { - m_delete_all = false; - m_category = "default"; - } - - const OptionDefinition* - GetDefinitions () - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_delete_all; - std::string m_category; - - }; - - CommandOptions m_options; - - virtual Options * - GetOptions () - { - return &m_options; - } - - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) - { - ConstString* name = (ConstString*)param; - return cate->Delete(*name, eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); - } - -public: - CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type synthetic delete", - "Delete an existing synthetic provider for a type.", - NULL), - m_options(interpreter) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlain; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - } - - ~CommandObjectTypeSynthDelete () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - const size_t argc = command.GetArgumentCount(); - - if (argc != 1) - { - result.AppendErrorWithFormat ("%s takes 1 arg.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const char* typeA = command.GetArgumentAtIndex(0); - ConstString typeCS(typeA); - - if (!typeCS) - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - if (m_options.m_delete_all) - { - DataVisualization::Categories::LoopThrough(PerCategoryCallback, (void*)&typeCS); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - - lldb::TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString(m_options.m_category.c_str()), category); - - bool delete_category = category->GetTypeSyntheticsContainer()->Delete(typeCS); - delete_category = category->GetRegexTypeSyntheticsContainer()->Delete(typeCS) || delete_category; - - if (delete_category) - { - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); - } - else - { - result.AppendErrorWithFormat ("no custom synthetic provider for %s.\n", typeA); - result.SetStatus(eReturnStatusFailed); - return false; - } - - } -}; - -OptionDefinition -CommandObjectTypeSynthDelete::CommandOptions::g_option_table[] = -{ - { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Delete from every category."}, - { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Delete from given category."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } -}; - -#endif // #ifndef LLDB_DISABLE_PYTHON - -//------------------------------------------------------------------------- -// CommandObjectTypeFilterClear -//------------------------------------------------------------------------- - -class CommandObjectTypeFilterClear : public CommandObjectParsed -{ -private: - - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () - { - m_delete_all = false; - } - - const OptionDefinition* - GetDefinitions () - { - return g_option_table; - } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_delete_all; - bool m_delete_named; - }; - - CommandOptions m_options; - - virtual Options * - GetOptions () - { - return &m_options; - } - - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) - { - cate->Clear(eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter); - return true; - - } - -public: - CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type filter clear", - "Delete all existing filters.", - NULL), - m_options(interpreter) - { - } - - ~CommandObjectTypeFilterClear () - { - } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) - { - - if (m_options.m_delete_all) - DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); - - else - { - lldb::TypeCategoryImplSP category; - if (command.GetArgumentCount() > 0) - { - const char* cat_name = command.GetArgumentAtIndex(0); - ConstString cat_nameCS(cat_name); - DataVisualization::Categories::GetCategory(cat_nameCS, category); - } - else - DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->GetTypeFiltersContainer()->Clear(); - category->GetRegexTypeFiltersContainer()->Clear(); - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } - -}; - -OptionDefinition -CommandObjectTypeFilterClear::CommandOptions::g_option_table[] = -{ - { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } -}; - -#ifndef LLDB_DISABLE_PYTHON -//------------------------------------------------------------------------- -// CommandObjectTypeSynthClear -//------------------------------------------------------------------------- - -class CommandObjectTypeSynthClear : public CommandObjectParsed -{ -private: - - class CommandOptions : public Options - { - public: - - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) - { - case 'a': - m_delete_all = true; - break; - default: - error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); - break; - } - - return error; - } - - void - OptionParsingStarting () + if (argc == 1) { - m_delete_all = false; + regex.reset(new RegularExpression()); + const char* arg = command.GetArgumentAtIndex(0); + if (!regex->Compile(arg)) + { + result.AppendErrorWithFormat("syntax error in category regular expression '%s'", arg); + result.SetStatus(eReturnStatusFailed); + return false; + } } - - const OptionDefinition* - GetDefinitions () + else if (argc != 0) { - return g_option_table; + result.AppendErrorWithFormat ("%s takes 0 or one arg.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. + DataVisualization::Categories::ForEach( [®ex, &result] (const lldb::TypeCategoryImplSP& category_sp) -> bool { + if (regex) + { + bool escape = true; + if (0 == strcmp(category_sp->GetName(), regex->GetText())) + { + escape = false; + } + else if (regex->Execute(category_sp->GetName())) + { + escape = false; + } + + if (escape) + return true; + } + + result.GetOutputStream().Printf("Category: %s\n", category_sp->GetDescription().c_str()); + + return true; + }); - bool m_delete_all; - bool m_delete_named; - }; + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } - CommandOptions m_options; +}; + +//------------------------------------------------------------------------- +// CommandObjectTypeFilterList +//------------------------------------------------------------------------- + +class CommandObjectTypeFilterList : public CommandObjectTypeFormatterList +{ +public: - virtual Options * - GetOptions () + CommandObjectTypeFilterList (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterList(interpreter, + "type filter list", + "Show a list of current filters.") { - return &m_options; } +}; + +#ifndef LLDB_DISABLE_PYTHON + +//------------------------------------------------------------------------- +// CommandObjectTypeSynthList +//------------------------------------------------------------------------- + +class CommandObjectTypeSynthList : public CommandObjectTypeFormatterList +{ +public: - static bool - PerCategoryCallback(void* param, - const lldb::TypeCategoryImplSP& cate) + CommandObjectTypeSynthList (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterList(interpreter, + "type synthetic list", + "Show a list of current synthetic providers.") { - cate->Clear(eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth); - return true; - } - +}; + +#endif // #ifndef LLDB_DISABLE_PYTHON +//------------------------------------------------------------------------- +// CommandObjectTypeFilterDelete +//------------------------------------------------------------------------- + +class CommandObjectTypeFilterDelete : public CommandObjectTypeFormatterDelete +{ public: - CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : - CommandObjectParsed (interpreter, - "type synthetic clear", - "Delete all existing synthetic providers.", - NULL), - m_options(interpreter) + CommandObjectTypeFilterDelete (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterDelete (interpreter, + eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, + "type filter delete", + "Delete an existing filter for a type.") { } - ~CommandObjectTypeSynthClear () + ~CommandObjectTypeFilterDelete () override { } - -protected: - bool - DoExecute (Args& command, CommandReturnObject &result) +}; + +#ifndef LLDB_DISABLE_PYTHON + +//------------------------------------------------------------------------- +// CommandObjectTypeSynthDelete +//------------------------------------------------------------------------- + +class CommandObjectTypeSynthDelete : public CommandObjectTypeFormatterDelete +{ +public: + CommandObjectTypeSynthDelete (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterDelete (interpreter, + eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, + "type synthetic delete", + "Delete an existing synthetic provider for a type.") { - - if (m_options.m_delete_all) - DataVisualization::Categories::LoopThrough(PerCategoryCallback, NULL); - - else - { - lldb::TypeCategoryImplSP category; - if (command.GetArgumentCount() > 0) - { - const char* cat_name = command.GetArgumentAtIndex(0); - ConstString cat_nameCS(cat_name); - DataVisualization::Categories::GetCategory(cat_nameCS, category); - } - else - DataVisualization::Categories::GetCategory(ConstString(NULL), category); - category->GetTypeSyntheticsContainer()->Clear(); - category->GetRegexTypeSyntheticsContainer()->Clear(); - } - - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); } + ~CommandObjectTypeSynthDelete () override + { + } }; -OptionDefinition -CommandObjectTypeSynthClear::CommandOptions::g_option_table[] = +#endif // #ifndef LLDB_DISABLE_PYTHON + +//------------------------------------------------------------------------- +// CommandObjectTypeFilterClear +//------------------------------------------------------------------------- + +class CommandObjectTypeFilterClear : public CommandObjectTypeFormatterClear { - { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Clear every category."}, - { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +public: + CommandObjectTypeFilterClear (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterClear (interpreter, + eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter, + "type filter clear", + "Delete all existing filter.") + { + } }; +#ifndef LLDB_DISABLE_PYTHON +//------------------------------------------------------------------------- +// CommandObjectTypeSynthClear +//------------------------------------------------------------------------- + +class CommandObjectTypeSynthClear : public CommandObjectTypeFormatterClear +{ +public: + CommandObjectTypeSynthClear (CommandInterpreter &interpreter) : + CommandObjectTypeFormatterClear (interpreter, + eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth, + "type synthetic clear", + "Delete all existing synthetic providers.") + { + } +}; bool CommandObjectTypeSynthAdd::Execute_HandwritePython (Args& command, CommandReturnObject &result) @@ -3956,10 +2982,10 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, cascade through typedef chains."}, { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, - { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-tNULL, ype objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, - { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument,NULL, NULL, 0, eArgTypeNone, "Type Python code to generate a class that NULL, provides synthetic children."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; @@ -3981,11 +3007,10 @@ private: { } - virtual - ~CommandOptions (){} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -4023,7 +3048,7 @@ private: } void - OptionParsingStarting () + OptionParsingStarting () override { m_cascade = true; m_skip_pointers = false; @@ -4035,7 +3060,7 @@ private: } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -4062,8 +3087,8 @@ private: CommandOptions m_options; - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -4076,7 +3101,7 @@ private: bool AddFilter(ConstString type_name, - SyntheticChildrenSP entry, + TypeFilterImplSP entry, FilterFormatType type, std::string category_name, Error* error) @@ -4175,13 +3200,13 @@ all children of my_foo as if no filter was defined:" R"( ); } - ~CommandObjectTypeFilterAdd () + ~CommandObjectTypeFilterAdd () override { } protected: bool - DoExecute (Args& command, CommandReturnObject &result) + DoExecute (Args& command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -4199,19 +3224,15 @@ protected: return false; } - SyntheticChildrenSP entry; - - TypeFilterImpl* impl = new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). - SetSkipPointers(m_options.m_skip_pointers). - SetSkipReferences(m_options.m_skip_references)); - - entry.reset(impl); + TypeFilterImplSP entry(new TypeFilterImpl(SyntheticChildren::Flags().SetCascades(m_options.m_cascade). + SetSkipPointers(m_options.m_skip_pointers). + SetSkipReferences(m_options.m_skip_references))); // go through the expression paths CommandOptions::ExpressionPathsIterator begin, end = m_options.m_expr_paths.end(); for (begin = m_options.m_expr_paths.begin(); begin != end; begin++) - impl->AddExpressionPath(*begin); + entry->AddExpressionPath(*begin); // now I have a valid provider, let's add it to every type @@ -4266,6 +3287,215 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; +//---------------------------------------------------------------------- +// "type lookup" +//---------------------------------------------------------------------- +class CommandObjectTypeLookup : public CommandObjectRaw +{ +protected: + + class CommandOptions : public OptionGroup + { + public: + + CommandOptions () : + OptionGroup(), + m_show_help(false), + m_language(eLanguageTypeUnknown) + {} + + ~CommandOptions () override {} + + uint32_t + GetNumDefinitions () override + { + return 3; + } + + const OptionDefinition* + GetDefinitions () override + { + return g_option_table; + } + + Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) override + { + Error error; + + const int short_option = g_option_table[option_idx].short_option; + + switch (short_option) + { + case 'h': + m_show_help = true; + break; + + case 'l': + m_language = Language::GetLanguageTypeFromString(option_value); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting (CommandInterpreter &interpreter) override + { + m_show_help = false; + m_language = eLanguageTypeUnknown; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + bool m_show_help; + lldb::LanguageType m_language; + }; + + OptionGroupOptions m_option_group; + CommandOptions m_command_options; + +public: + + CommandObjectTypeLookup (CommandInterpreter &interpreter) : + CommandObjectRaw (interpreter, + "type lookup", + "Lookup a type by name in the select target.", + "type lookup ", + eCommandRequiresTarget), + m_option_group(interpreter), + m_command_options() + { + m_option_group.Append(&m_command_options); + m_option_group.Finalize(); + } + + ~CommandObjectTypeLookup () override + { + } + + Options * + GetOptions () override + { + return &m_option_group; + } + + bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) override + { + if (!raw_command_line || !raw_command_line[0]) + { + result.SetError("type lookup cannot be invoked without a type name as argument"); + return false; + } + + m_option_group.NotifyOptionParsingStarting(); + + const char * name_of_type = NULL; + + if (raw_command_line[0] == '-') + { + // We have some options and these options MUST end with --. + const char *end_options = NULL; + const char *s = raw_command_line; + while (s && s[0]) + { + end_options = ::strstr (s, "--"); + if (end_options) + { + end_options += 2; // Get past the "--" + if (::isspace (end_options[0])) + { + name_of_type = end_options; + while (::isspace (*name_of_type)) + ++name_of_type; + break; + } + } + s = end_options; + } + + if (end_options) + { + Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); + if (!ParseOptions (args, result)) + return false; + + Error error (m_option_group.NotifyOptionParsingFinished()); + if (error.Fail()) + { + result.AppendError (error.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + if (nullptr == name_of_type) + name_of_type = raw_command_line; + + TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget()); + const bool fill_all_in = true; + ExecutionContext exe_ctx(target_sp.get(), fill_all_in); + ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope(); + + bool any_found = false; + + std::vector languages; + + if (m_command_options.m_language == eLanguageTypeUnknown) + { + // FIXME: hardcoding languages is not good + languages.push_back(Language::FindPlugin(eLanguageTypeObjC)); + languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus)); + } + else + { + languages.push_back(Language::FindPlugin(m_command_options.m_language)); + } + + for (Language* language : languages) + { + if (!language) + continue; + + if (auto scavenger = language->GetTypeScavenger()) + { + Language::TypeScavenger::ResultSet search_results; + if (scavenger->Find(best_scope, name_of_type, search_results) > 0) + { + for (const auto& search_result : search_results) + { + if (search_result && search_result->IsValid()) + { + any_found = true; + search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help); + } + } + } + } + } + + result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult); + return true; + } + +}; + +OptionDefinition +CommandObjectTypeLookup::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display available help for types"}, + { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Which language's types should the search scope be"}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + template class CommandObjectFormatterInfo : public CommandObjectRaw { @@ -4293,14 +3523,13 @@ public: SetSyntax(syntax.GetData()); } - virtual - ~CommandObjectFormatterInfo () + ~CommandObjectFormatterInfo () override { } protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result) + bool + DoExecute (const char *command, CommandReturnObject &result) override { auto target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); auto frame_sp = target_sp->GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame(); @@ -4365,7 +3594,7 @@ public: } - ~CommandObjectTypeFormat () + ~CommandObjectTypeFormat () override { } }; @@ -4393,7 +3622,7 @@ public: } - ~CommandObjectTypeSynth () + ~CommandObjectTypeSynth () override { } }; @@ -4416,7 +3645,7 @@ public: } - ~CommandObjectTypeFilter () + ~CommandObjectTypeFilter () override { } }; @@ -4430,6 +3659,7 @@ public: "A set of commands for operating on categories", "type category [] ") { + LoadSubCommand ("define", CommandObjectSP (new CommandObjectTypeCategoryDefine (interpreter))); LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTypeCategoryEnable (interpreter))); LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTypeCategoryDisable (interpreter))); LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeCategoryDelete (interpreter))); @@ -4437,7 +3667,7 @@ public: } - ~CommandObjectTypeCategory () + ~CommandObjectTypeCategory () override { } }; @@ -4463,7 +3693,7 @@ public: } - ~CommandObjectTypeSummary () + ~CommandObjectTypeSummary () override { } }; @@ -4485,11 +3715,10 @@ CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) : #ifndef LLDB_DISABLE_PYTHON LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter))); #endif + LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter))); } CommandObjectType::~CommandObjectType () { } - - diff --git a/source/Commands/CommandObjectType.h b/source/Commands/CommandObjectType.h index c796902cf3bd..54f4a33c6f65 100644 --- a/source/Commands/CommandObjectType.h +++ b/source/Commands/CommandObjectType.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes - // Other libraries and framework includes // Project includes @@ -28,10 +27,9 @@ class CommandObjectType : public CommandObjectMultiword public: CommandObjectType (CommandInterpreter &interpreter); - virtual - ~CommandObjectType (); + ~CommandObjectType() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectType_h_ +#endif // liblldb_CommandObjectType_h_ diff --git a/source/Commands/CommandObjectVersion.h b/source/Commands/CommandObjectVersion.h index 1fdbed60c65d..30ba9d1235d9 100644 --- a/source/Commands/CommandObjectVersion.h +++ b/source/Commands/CommandObjectVersion.h @@ -28,16 +28,14 @@ public: CommandObjectVersion (CommandInterpreter &interpreter); - virtual - ~CommandObjectVersion (); + ~CommandObjectVersion() override; protected: - virtual bool - DoExecute (Args& args, - CommandReturnObject &result); - + bool + DoExecute(Args& args, + CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectVersion_h_ +#endif // liblldb_CommandObjectVersion_h_ diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp index 414e78403cc8..a97f5ade6460 100644 --- a/source/Commands/CommandObjectWatchpoint.cpp +++ b/source/Commands/CommandObjectWatchpoint.cpp @@ -104,7 +104,7 @@ CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args std::pair Pair; size_t i; int32_t idx; - // Go through the argments and make a canonical form of arg list containing + // Go through the arguments and make a canonical form of arg list containing // only numbers with possible "-" in between. for (i = 0; i < args.GetArgumentCount(); ++i) { llvm::StringRef Arg(args.GetArgumentAtIndex(i)); @@ -178,11 +178,10 @@ public: m_arguments.push_back(arg); } - virtual - ~CommandObjectWatchpointList () {} + ~CommandObjectWatchpointList () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -197,11 +196,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -226,13 +224,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_level = lldb::eDescriptionLevelFull; } const OptionDefinition * - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -248,8 +246,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == NULL) @@ -361,13 +359,12 @@ public: m_arguments.push_back(arg); } - virtual - ~CommandObjectWatchpointEnable () {} + ~CommandObjectWatchpointEnable () override {} protected: - virtual bool + bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (!CheckTargetForWatchpointOperations(target, result)) @@ -441,12 +438,11 @@ public: } - virtual - ~CommandObjectWatchpointDisable () {} + ~CommandObjectWatchpointDisable () override {} protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (!CheckTargetForWatchpointOperations(target, result)) @@ -524,12 +520,11 @@ public: m_arguments.push_back(arg); } - virtual - ~CommandObjectWatchpointDelete () {} + ~CommandObjectWatchpointDelete () override {} protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (!CheckTargetForWatchpointOperations(target, result)) @@ -607,11 +602,10 @@ public: m_arguments.push_back(arg); } - virtual - ~CommandObjectWatchpointIgnore () {} + ~CommandObjectWatchpointIgnore () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -626,11 +620,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -653,13 +646,13 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_ignore_count = 0; } const OptionDefinition * - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -675,9 +668,9 @@ public: }; protected: - virtual bool + bool DoExecute (Args& command, - CommandReturnObject &result) + CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (!CheckTargetForWatchpointOperations(target, result)) @@ -763,11 +756,10 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectWatchpointModify () {} + ~CommandObjectWatchpointModify () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } @@ -783,11 +775,10 @@ public: { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -810,14 +801,14 @@ public: } void - OptionParsingStarting () + OptionParsingStarting () override { m_condition.clear(); m_condition_passed = false; } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -833,8 +824,8 @@ public: }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (!CheckTargetForWatchpointOperations(target, result)) @@ -958,11 +949,10 @@ corresponding to the byte size of the data type." m_option_group.Finalize(); } - virtual - ~CommandObjectWatchpointSetVariable () {} + ~CommandObjectWatchpointSetVariable () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } @@ -983,8 +973,8 @@ protected: return 0; } - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); StackFrame *frame = m_exe_ctx.GetFramePtr(); @@ -1048,7 +1038,7 @@ protected: valobj_sp = valobj_list.GetValueObjectAtIndex(0); } - ClangASTType clang_type; + CompilerType compiler_type; if (valobj_sp) { @@ -1061,7 +1051,7 @@ protected: size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() : m_option_watchpoint.watch_size; } - clang_type = valobj_sp->GetClangType(); + compiler_type = valobj_sp->GetCompilerType(); } else { @@ -1078,7 +1068,7 @@ protected: uint32_t watch_type = m_option_watchpoint.watch_type; error.Clear(); - Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get(); + Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get(); if (wp) { wp->SetWatchSpec(command.GetArgumentAtIndex(0)); @@ -1169,22 +1159,21 @@ Examples: } - virtual - ~CommandObjectWatchpointSetExpression () {} + ~CommandObjectWatchpointSetExpression () override {} // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. - virtual bool - WantsCompletion() { return true; } + bool + WantsCompletion() override { return true; } - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_option_group; } protected: - virtual bool - DoExecute (const char *raw_command, CommandReturnObject &result) + bool + DoExecute (const char *raw_command, CommandReturnObject &result) override { m_option_group.NotifyOptionParsingStarting(); // This is a raw command, so notify the option group @@ -1295,10 +1284,10 @@ protected: // Fetch the type from the value object, the type of the watched object is the pointee type /// of the expression, so convert to that if we found a valid type. - ClangASTType clang_type(valobj_sp->GetClangType()); + CompilerType compiler_type(valobj_sp->GetCompilerType()); Error error; - Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get(); + Watchpoint *wp = target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error).get(); if (wp) { Stream &output_stream = result.GetOutputStream(); @@ -1345,8 +1334,7 @@ public: } - virtual - ~CommandObjectWatchpointSet () {} + ~CommandObjectWatchpointSet () override {} }; diff --git a/source/Commands/CommandObjectWatchpoint.h b/source/Commands/CommandObjectWatchpoint.h index 1b1ebd7764a3..b1926dc2ad7d 100644 --- a/source/Commands/CommandObjectWatchpoint.h +++ b/source/Commands/CommandObjectWatchpoint.h @@ -30,14 +30,12 @@ class CommandObjectMultiwordWatchpoint : public CommandObjectMultiword public: CommandObjectMultiwordWatchpoint (CommandInterpreter &interpreter); - virtual - ~CommandObjectMultiwordWatchpoint (); + ~CommandObjectMultiwordWatchpoint() override; static bool VerifyWatchpointIDs(Target *target, Args &args, std::vector &wp_ids); - }; } // namespace lldb_private -#endif // liblldb_CommandObjectWatchpoint_h_ +#endif // liblldb_CommandObjectWatchpoint_h_ diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index 84342cc8ffdf..2fa849f97674 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -169,17 +169,16 @@ are no syntax errors may indicate that a function was declared but never called. m_arguments.push_back (arg); } - virtual - ~CommandObjectWatchpointCommandAdd () {} + ~CommandObjectWatchpointCommandAdd () override {} - virtual Options * - GetOptions () + Options * + GetOptions () override { return &m_options; } - virtual void - IOHandlerActivated (IOHandler &io_handler) + void + IOHandlerActivated (IOHandler &io_handler) override { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) @@ -190,8 +189,8 @@ are no syntax errors may indicate that a function was declared but never called. } - virtual void - IOHandlerInputComplete (IOHandler &io_handler, std::string &line) + void + IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override { io_handler.SetIsDone(true); @@ -301,11 +300,10 @@ are no syntax errors may indicate that a function was declared but never called. { } - virtual - ~CommandOptions () {} + ~CommandOptions () override {} - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) override { Error error; const int short_option = m_getopt_table[option_idx].val; @@ -356,7 +354,7 @@ are no syntax errors may indicate that a function was declared but never called. return error; } void - OptionParsingStarting () + OptionParsingStarting () override { m_use_commands = true; m_use_script_language = false; @@ -369,7 +367,7 @@ are no syntax errors may indicate that a function was declared but never called. } const OptionDefinition* - GetDefinitions () + GetDefinitions () override { return g_option_table; } @@ -392,8 +390,8 @@ are no syntax errors may indicate that a function was declared but never called. }; protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); @@ -550,12 +548,11 @@ public: } - virtual - ~CommandObjectWatchpointCommandDelete () {} + ~CommandObjectWatchpointCommandDelete () override {} protected: - virtual bool - DoExecute (Args& command, CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); @@ -641,13 +638,11 @@ public: m_arguments.push_back (arg); } - virtual - ~CommandObjectWatchpointCommandList () {} + ~CommandObjectWatchpointCommandList () override {} protected: - virtual bool - DoExecute (Args& command, - CommandReturnObject &result) + bool + DoExecute (Args& command, CommandReturnObject &result) override { Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); diff --git a/source/Commands/CommandObjectWatchpointCommand.h b/source/Commands/CommandObjectWatchpointCommand.h index 3bc9b3537db7..d77b32a2fd4d 100644 --- a/source/Commands/CommandObjectWatchpointCommand.h +++ b/source/Commands/CommandObjectWatchpointCommand.h @@ -13,7 +13,6 @@ // C Includes // C++ Includes - // Other libraries and framework includes // Project includes @@ -33,11 +32,9 @@ class CommandObjectWatchpointCommand : public CommandObjectMultiword public: CommandObjectWatchpointCommand (CommandInterpreter &interpreter); - virtual - ~CommandObjectWatchpointCommand (); - + ~CommandObjectWatchpointCommand() override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectWatchpointCommand_h_ +#endif // liblldb_CommandObjectWatchpointCommand_h_ diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index 1cd7a7447b7f..83100dea93bc 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -179,7 +179,7 @@ ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, buf[k_buf_len] = '\0'; // NULL terminate // Byte order and address size don't matter for C string dumping.. - DataExtractor data (buf, sizeof(buf), lldb::endian::InlHostByteOrder(), 4); + DataExtractor data (buf, sizeof(buf), endian::InlHostByteOrder(), 4); size_t total_len = 0; size_t bytes_read; Address curr_address(address); @@ -367,21 +367,29 @@ Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target) } addr_t -Address::GetOpcodeLoadAddress (Target *target) const +Address::GetOpcodeLoadAddress (Target *target, AddressClass addr_class) const { addr_t code_addr = GetLoadAddress (target); if (code_addr != LLDB_INVALID_ADDRESS) - code_addr = target->GetOpcodeLoadAddress (code_addr, GetAddressClass()); + { + if (addr_class == eAddressClassInvalid) + addr_class = GetAddressClass(); + code_addr = target->GetOpcodeLoadAddress (code_addr, addr_class); + } return code_addr; } bool -Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target) +Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target, AddressClass addr_class) { if (SetLoadAddress (load_addr, target)) { if (target) - m_offset = target->GetOpcodeLoadAddress (m_offset, GetAddressClass()); + { + if (addr_class == eAddressClassInvalid) + addr_class = GetAddressClass(); + m_offset = target->GetOpcodeLoadAddress (m_offset, addr_class); + } return true; } return false; @@ -455,6 +463,20 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum case DumpStyleLoadAddress: { addr_t load_addr = GetLoadAddress (target); + + /* + * MIPS: + * Display address in compressed form for MIPS16 or microMIPS + * if the address belongs to eAddressClassCodeAlternateISA. + */ + if (target) + { + const llvm::Triple::ArchType llvm_arch = target->GetArchitecture().GetMachine(); + if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) + load_addr = GetCallableLoadAddress (target); + } + if (load_addr == LLDB_INVALID_ADDRESS) { if (fallback_style != DumpStyleInvalid) diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp index 1c6205fa6bdf..293002ad517f 100644 --- a/source/Core/AddressResolverName.cpp +++ b/source/Core/AddressResolverName.cpp @@ -13,7 +13,6 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index 2dc001a9047f..ffe717f29c43 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -419,8 +419,8 @@ ArchSpec::ArchSpec() : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id (), - m_flags (0) + m_flags (0), + m_distribution_id () { } @@ -428,8 +428,8 @@ ArchSpec::ArchSpec (const char *triple_cstr, Platform *platform) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id (), - m_flags (0) + m_flags (0), + m_distribution_id () { if (triple_cstr) SetTriple(triple_cstr, platform); @@ -440,8 +440,8 @@ ArchSpec::ArchSpec (const char *triple_cstr) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id (), - m_flags (0) + m_flags (0), + m_distribution_id () { if (triple_cstr) SetTriple(triple_cstr); @@ -451,8 +451,8 @@ ArchSpec::ArchSpec(const llvm::Triple &triple) : m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id (), - m_flags (0) + m_flags (0), + m_distribution_id () { SetTriple(triple); } @@ -461,8 +461,8 @@ ArchSpec::ArchSpec (ArchitectureType arch_type, uint32_t cpu, uint32_t subtype) m_triple (), m_core (kCore_invalid), m_byte_order (eByteOrderInvalid), - m_distribution_id (), - m_flags (0) + m_flags (0), + m_distribution_id () { SetArchitecture (arch_type, cpu, subtype); } @@ -602,7 +602,15 @@ ArchSpec::GetAddressByteSize() const { const CoreDefinition *core_def = FindCoreDefinition (m_core); if (core_def) - return core_def->addr_byte_size; + { + if (core_def->machine == llvm::Triple::mips64 || core_def->machine == llvm::Triple::mips64el) + { + // For N32/O32 applications Address size is 4 bytes. + if (m_flags & (eMIPSABI_N32 | eMIPSABI_O32)) + return 4; + } + return core_def->addr_byte_size; + } return 0; } @@ -836,14 +844,17 @@ ArchSpec::SetTriple (const char *triple_cstr, Platform *platform) void ArchSpec::MergeFrom(const ArchSpec &other) { - if (GetTriple().getVendor() == llvm::Triple::UnknownVendor && !TripleVendorWasSpecified()) + if (TripleVendorIsUnspecifiedUnknown() && !other.TripleVendorIsUnspecifiedUnknown()) GetTriple().setVendor(other.GetTriple().getVendor()); - if (GetTriple().getOS() == llvm::Triple::UnknownOS && !TripleOSWasSpecified()) + if (TripleOSIsUnspecifiedUnknown() && !other.TripleOSIsUnspecifiedUnknown()) GetTriple().setOS(other.GetTriple().getOS()); if (GetTriple().getArch() == llvm::Triple::UnknownArch) GetTriple().setArch(other.GetTriple().getArch()); - if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment) - GetTriple().setEnvironment(other.GetTriple().getEnvironment()); + if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && !TripleVendorWasSpecified()) + { + if (other.TripleVendorWasSpecified()) + GetTriple().setEnvironment(other.GetTriple().getEnvironment()); + } } bool @@ -868,29 +879,14 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su if (arch_type == eArchTypeMachO) { m_triple.setVendor (llvm::Triple::Apple); - switch (core_def->machine) - { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::thumb: - m_triple.setOS (llvm::Triple::IOS); - break; - - case llvm::Triple::x86: - case llvm::Triple::x86_64: - // Don't set the OS for x86_64 or for x86 as we want to leave it as an "unspecified unknown" - // which means if we ask for the OS from the llvm::Triple we get back llvm::Triple::UnknownOS, but - // if we ask for the string value for the OS it will come back empty (unspecified). - // We do this because we now have iOS and MacOSX as the OS values for x86 and x86_64 for - // normal desktop and simulator binaries. And if we compare a "x86_64-apple-ios" to a "x86_64-apple-" - // triple, it will say it is compatible (because the OS is unspecified in the second one and will match - // anything in the first - break; - - default: - m_triple.setOS (llvm::Triple::MacOSX); - break; - } + + // 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. } else if (arch_type == eArchTypeELF) { @@ -904,6 +900,11 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS (llvm::Triple::OSType::Solaris); break; } } + else + { + m_triple.setVendor (llvm::Triple::UnknownVendor); + m_triple.setOS (llvm::Triple::UnknownOS); + } // Fall back onto setting the machine type if the arch by name failed... if (m_triple.getArch () == llvm::Triple::UnknownArch) m_triple.setArch (core_def->machine); @@ -966,15 +967,12 @@ ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor(); if (lhs_triple_vendor != rhs_triple_vendor) { - if (exact_match) - { - const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); - const bool lhs_vendor_specified = TripleVendorWasSpecified(); - // Both architectures had the vendor specified, so if they aren't - // equal then we return false - if (rhs_vendor_specified && lhs_vendor_specified) - return false; - } + const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); + const bool lhs_vendor_specified = TripleVendorWasSpecified(); + // Both architectures had the vendor specified, so if they aren't + // equal then we return false + if (rhs_vendor_specified && lhs_vendor_specified) + return false; // Only fail if both vendor types are not unknown if (lhs_triple_vendor != llvm::Triple::UnknownVendor && @@ -986,15 +984,12 @@ ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS(); if (lhs_triple_os != rhs_triple_os) { - if (exact_match) - { - const bool rhs_os_specified = rhs.TripleOSWasSpecified(); - const bool lhs_os_specified = TripleOSWasSpecified(); - // Both architectures had the OS specified, so if they aren't - // equal then we return false - if (rhs_os_specified && lhs_os_specified) - return false; - } + const bool rhs_os_specified = rhs.TripleOSWasSpecified(); + const bool lhs_os_specified = TripleOSWasSpecified(); + // Both architectures had the OS specified, so if they aren't + // equal then we return false + if (rhs_os_specified && lhs_os_specified) + return false; // Only fail if both os types are not unknown if (lhs_triple_os != llvm::Triple::UnknownOS && @@ -1103,6 +1098,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in return true; break; + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // Cortex-M0 - ARMv6-M - armv6m + // Cortex-M3 - ARMv7-M - armv7m + // Cortex-M4 - ARMv7E-M - armv7em case ArchSpec::eCore_arm_armv7em: if (!enforce_exact_match) { @@ -1118,6 +1117,10 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in } break; + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // Cortex-M0 - ARMv6-M - armv6m + // Cortex-M3 - ARMv7-M - armv7m + // Cortex-M4 - ARMv7E-M - armv7em case ArchSpec::eCore_arm_armv7m: if (!enforce_exact_match) { @@ -1428,3 +1431,62 @@ ArchSpec::GetStopInfoOverrideCallback () const return StopInfoOverrideCallbackTypeARM; return NULL; } + +bool +ArchSpec::IsFullySpecifiedTriple () const +{ + const auto& user_specified_triple = GetTriple(); + + bool user_triple_fully_specified = false; + + if ((user_specified_triple.getOS() != llvm::Triple::UnknownOS) || TripleOSWasSpecified()) + { + if ((user_specified_triple.getVendor() != llvm::Triple::UnknownVendor) || TripleVendorWasSpecified()) + { + const unsigned unspecified = 0; + if (user_specified_triple.getOSMajorVersion() != unspecified) + { + user_triple_fully_specified = true; + } + } + } + + return user_triple_fully_specified; +} + +void +ArchSpec::PiecewiseTripleCompare (const ArchSpec &other, + bool &arch_different, + bool &vendor_different, + bool &os_different, + bool &os_version_different, + bool &env_different) +{ + const llvm::Triple &me(GetTriple()); + const llvm::Triple &them(other.GetTriple()); + + arch_different = (me.getArch() != them.getArch()); + + vendor_different = (me.getVendor() != them.getVendor()); + + os_different = (me.getOS() != them.getOS()); + + os_version_different = (me.getOSMajorVersion() != them.getOSMajorVersion()); + + env_different = (me.getEnvironment() != them.getEnvironment()); +} + +void +ArchSpec::DumpTriple(Stream &s) const +{ + const llvm::Triple &triple = GetTriple(); + llvm::StringRef arch_str = triple.getArchName(); + llvm::StringRef vendor_str = triple.getVendorName(); + llvm::StringRef os_str = triple.getOSName(); + + s.Printf("%s-%s-%s", + arch_str.empty() ? "*" : arch_str.str().c_str(), + vendor_str.empty() ? "*" : vendor_str.str().c_str(), + os_str.empty() ? "*" : os_str.str().c_str() + ); +} diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp index 77daeb14840d..e417347579eb 100644 --- a/source/Core/ConnectionSharedMemory.cpp +++ b/source/Core/ConnectionSharedMemory.cpp @@ -16,10 +16,10 @@ #ifdef _WIN32 #include "lldb/Host/windows/windows.h" #else -#include #include #include #include +#include #endif // C++ Includes diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp index 85f8d3c65cd9..c2e95d801723 100644 --- a/source/Core/ConstString.cpp +++ b/source/Core/ConstString.cpp @@ -8,39 +8,21 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/ConstString.h" #include "lldb/Core/Stream.h" -#include "lldb/Host/Mutex.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/RWMutex.h" -#include // std::once +#include +#include using namespace lldb_private; - class Pool { public: typedef const char * StringPoolValueType; typedef llvm::StringMap StringPool; typedef llvm::StringMapEntry StringPoolEntryType; - - //------------------------------------------------------------------ - // Default constructor - // - // Initialize the member variables and create the empty string. - //------------------------------------------------------------------ - Pool () : - m_mutex (Mutex::eMutexTypeRecursive), - m_string_map () - { - } - - //------------------------------------------------------------------ - // Destructor - //------------------------------------------------------------------ - ~Pool () - { - } - static StringPoolEntryType & GetStringMapEntryFromKeyData (const char *keyData) @@ -54,7 +36,9 @@ public: { if (ccstr) { - const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr); + const uint8_t h = hash (llvm::StringRef(ccstr)); + llvm::sys::SmartScopedReader rlock(m_string_pools[h].m_mutex); + const StringPoolEntryType& entry = GetStringMapEntryFromKeyData (ccstr); return entry.getKey().size(); } return 0; @@ -64,7 +48,11 @@ public: GetMangledCounterpart (const char *ccstr) const { if (ccstr) + { + const uint8_t h = hash (llvm::StringRef(ccstr)); + llvm::sys::SmartScopedReader rlock(m_string_pools[h].m_mutex); return GetStringMapEntryFromKeyData (ccstr).getValue(); + } return 0; } @@ -73,8 +61,16 @@ public: { if (key_ccstr && value_ccstr) { - GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); - GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); + { + const uint8_t h = hash (llvm::StringRef(key_ccstr)); + llvm::sys::SmartScopedWriter wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); + } + { + const uint8_t h = hash (llvm::StringRef(value_ccstr)); + llvm::sys::SmartScopedWriter wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); + } return true; } return false; @@ -85,20 +81,15 @@ public: { if (cstr) return GetConstCStringWithLength (cstr, strlen (cstr)); - return NULL; + return nullptr; } const char * GetConstCStringWithLength (const char *cstr, size_t cstr_len) { if (cstr) - { - Mutex::Locker locker (m_mutex); - llvm::StringRef string_ref (cstr, cstr_len); - StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first; - return entry.getKeyData(); - } - return NULL; + return GetConstCStringWithStringRef(llvm::StringRef(cstr, cstr_len)); + return nullptr; } const char * @@ -106,11 +97,20 @@ public: { if (string_ref.data()) { - Mutex::Locker locker (m_mutex); - StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (string_ref, (StringPoolValueType)NULL)).first; + const uint8_t h = hash (string_ref); + + { + llvm::sys::SmartScopedReader rlock(m_string_pools[h].m_mutex); + auto it = m_string_pools[h].m_string_map.find (string_ref); + if (it != m_string_pools[h].m_string_map.end()) + return it->getKeyData(); + } + + llvm::sys::SmartScopedWriter wlock(m_string_pools[h].m_mutex); + StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (std::make_pair (string_ref, nullptr)).first; return entry.getKeyData(); } - return NULL; + return nullptr; } const char * @@ -118,19 +118,33 @@ public: { if (demangled_cstr) { - Mutex::Locker locker (m_mutex); - // Make string pool entry with the mangled counterpart already set - StringPoolEntryType& entry = *m_string_map.insert (std::make_pair (llvm::StringRef (demangled_cstr), mangled_ccstr)).first; - - // Extract the const version of the demangled_cstr - const char *demangled_ccstr = entry.getKeyData(); - // Now assign the demangled const string as the counterpart of the - // mangled const string... - GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); + const char *demangled_ccstr = nullptr; + + { + llvm::StringRef string_ref (demangled_cstr); + const uint8_t h = hash (string_ref); + llvm::sys::SmartScopedWriter 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; + + // Extract the const version of the demangled_cstr + demangled_ccstr = entry.getKeyData(); + } + + { + // 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 wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); + } + // Return the constant demangled C string return demangled_ccstr; } - return NULL; + return nullptr; } const char * @@ -141,7 +155,7 @@ public: const size_t trimmed_len = std::min (strlen (cstr), cstr_len); return GetConstCStringWithLength (cstr, trimmed_len); } - return NULL; + return nullptr; } //------------------------------------------------------------------ @@ -152,28 +166,31 @@ public: size_t MemorySize() const { - Mutex::Locker locker (m_mutex); size_t mem_size = sizeof(Pool); - const_iterator end = m_string_map.end(); - for (const_iterator pos = m_string_map.begin(); pos != end; ++pos) + for (const auto& pool : m_string_pools) { - mem_size += sizeof(StringPoolEntryType) + pos->getKey().size(); + llvm::sys::SmartScopedReader rlock(pool.m_mutex); + for (const auto& entry : pool.m_string_map) + mem_size += sizeof(StringPoolEntryType) + entry.getKey().size(); } return mem_size; } protected: - //------------------------------------------------------------------ - // Typedefs - //------------------------------------------------------------------ - typedef StringPool::iterator iterator; - typedef StringPool::const_iterator const_iterator; + uint8_t + hash(const llvm::StringRef &s) const + { + uint32_t h = llvm::HashString(s); + return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff; + } - //------------------------------------------------------------------ - // Member variables - //------------------------------------------------------------------ - mutable Mutex m_mutex; - StringPool m_string_map; + struct PoolEntry + { + mutable llvm::sys::SmartRWMutex m_mutex; + StringPool m_string_map; + }; + + std::array m_string_pools; }; //---------------------------------------------------------------------- @@ -191,7 +208,7 @@ static Pool & StringPool() { static std::once_flag g_pool_initialization_flag; - static Pool *g_string_pool = NULL; + static Pool *g_string_pool = nullptr; std::call_once(g_pool_initialization_flag, [] () { g_string_pool = new Pool(); @@ -228,8 +245,8 @@ ConstString::operator < (const ConstString& rhs) const if (lhs_string_ref.data() && rhs_string_ref.data()) return lhs_string_ref < rhs_string_ref; - // Else one of them was NULL, so if LHS is NULL then it is less than - return lhs_string_ref.data() == NULL; + // Else one of them was nullptr, so if LHS is nullptr then it is less than + return lhs_string_ref.data() == nullptr; } Stream& diff --git a/source/Core/CxaDemangle.cpp b/source/Core/CxaDemangle.cpp index bcc52ff39fe4..7d21138c2899 100644 --- a/source/Core/CxaDemangle.cpp +++ b/source/Core/CxaDemangle.cpp @@ -13,6 +13,7 @@ // - Included win32.h for snprintf implementation for MSVC // - Removed constexpr member initialization for MSVC // - Changed argument to alignas() to a literal for MSVC +// - Include for fprintf, stderr like entities. //---------------------------------------------------------------------- #if defined(_MSC_VER) @@ -40,6 +41,7 @@ #include #include #include +#include namespace lldb_private { diff --git a/source/Core/DataEncoder.cpp b/source/Core/DataEncoder.cpp index d21ca423892f..040d09647562 100644 --- a/source/Core/DataEncoder.cpp +++ b/source/Core/DataEncoder.cpp @@ -61,7 +61,7 @@ WriteSwappedInt64(unsigned char* ptr, unsigned offset, uint64_t value) DataEncoder::DataEncoder () : m_start (NULL), m_end (NULL), - m_byte_order(lldb::endian::InlHostByteOrder()), + m_byte_order(endian::InlHostByteOrder()), m_addr_size (sizeof(void*)), m_data_sp () { @@ -114,7 +114,7 @@ DataEncoder::Clear () { m_start = NULL; m_end = NULL; - m_byte_order = lldb::endian::InlHostByteOrder(); + m_byte_order = endian::InlHostByteOrder(); m_addr_size = sizeof(void*); m_data_sp.reset(); } @@ -240,7 +240,7 @@ DataEncoder::PutU16 (uint32_t offset, uint16_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) WriteSwappedInt16 (m_start, offset, value); else WriteInt16 (m_start, offset, value); @@ -255,7 +255,7 @@ DataEncoder::PutU32 (uint32_t offset, uint32_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) WriteSwappedInt32 (m_start, offset, value); else WriteInt32 (m_start, offset, value); @@ -270,7 +270,7 @@ DataEncoder::PutU64 (uint32_t offset, uint64_t value) { if (ValidOffsetForDataOfSize(offset, sizeof(value))) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) WriteSwappedInt64 (m_start, offset, value); else WriteInt64 (m_start, offset, value); diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp index 861bece98da9..dc7857fe9cb7 100644 --- a/source/Core/DataExtractor.cpp +++ b/source/Core/DataExtractor.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "clang/AST/ASTContext.h" @@ -130,8 +131,8 @@ ReadSwapInt64(const void* ptr) DataExtractor::DataExtractor () : m_start (NULL), m_end (NULL), - m_byte_order(lldb::endian::InlHostByteOrder()), - m_addr_size (4), + m_byte_order(endian::InlHostByteOrder()), + m_addr_size (sizeof(void *)), m_data_sp (), m_target_byte_size(1) { @@ -142,13 +143,16 @@ DataExtractor::DataExtractor () : // The data must stay around as long as this object is valid. //---------------------------------------------------------------------- DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) : - m_start ((uint8_t*)data), - m_end ((uint8_t*)data + length), + m_start (const_cast(reinterpret_cast(data))), + m_end (const_cast(reinterpret_cast(data)) + length), m_byte_order(endian), m_addr_size (addr_size), m_data_sp (), m_target_byte_size(target_byte_size) { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (addr_size == 4 || addr_size == 8); +#endif } //---------------------------------------------------------------------- @@ -166,6 +170,9 @@ DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uin m_data_sp (), m_target_byte_size(target_byte_size) { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (addr_size == 4 || addr_size == 8); +#endif SetData (data_sp); } @@ -184,6 +191,9 @@ DataExtractor::DataExtractor (const DataExtractor& data, offset_t offset, offset m_data_sp(), m_target_byte_size(target_byte_size) { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif if (data.ValidOffset(offset)) { offset_t bytes_available = data.GetByteSize() - offset; @@ -201,6 +211,9 @@ DataExtractor::DataExtractor (const DataExtractor& rhs) : m_data_sp (rhs.m_data_sp), m_target_byte_size(rhs.m_target_byte_size) { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif } //---------------------------------------------------------------------- @@ -237,8 +250,8 @@ DataExtractor::Clear () { m_start = NULL; m_end = NULL; - m_byte_order = lldb::endian::InlHostByteOrder(); - m_addr_size = 4; + m_byte_order = endian::InlHostByteOrder(); + m_addr_size = sizeof(void *); m_data_sp.reset(); } @@ -287,7 +300,7 @@ DataExtractor::SetData (const void *bytes, offset_t length, ByteOrder endian) } else { - m_start = (uint8_t *)bytes; + m_start = const_cast(reinterpret_cast(bytes)); m_end = m_start + length; } return GetByteSize(); @@ -311,6 +324,9 @@ lldb::offset_t DataExtractor::SetData (const DataExtractor& data, offset_t data_offset, offset_t data_length) { m_addr_size = data.m_addr_size; +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif // If "data" contains shared pointer to data, then we can use that if (data.m_data_sp.get()) { @@ -427,7 +443,7 @@ DataExtractor::GetU16 (offset_t *offset_ptr) const const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); if (data) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) val = ReadSwapInt16(data); else val = ReadInt16 (data); @@ -439,7 +455,7 @@ uint16_t DataExtractor::GetU16_unchecked (offset_t *offset_ptr) const { uint16_t val; - if (m_byte_order == lldb::endian::InlHostByteOrder()) + if (m_byte_order == endian::InlHostByteOrder()) val = ReadInt16 (m_start, *offset_ptr); else val = ReadSwapInt16(m_start, *offset_ptr); @@ -451,7 +467,7 @@ uint32_t DataExtractor::GetU32_unchecked (offset_t *offset_ptr) const { uint32_t val; - if (m_byte_order == lldb::endian::InlHostByteOrder()) + if (m_byte_order == endian::InlHostByteOrder()) val = ReadInt32 (m_start, *offset_ptr); else val = ReadSwapInt32 (m_start, *offset_ptr); @@ -463,7 +479,7 @@ uint64_t DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const { uint64_t val; - if (m_byte_order == lldb::endian::InlHostByteOrder()) + if (m_byte_order == endian::InlHostByteOrder()) val = ReadInt64 (m_start, *offset_ptr); else val = ReadSwapInt64 (m_start, *offset_ptr); @@ -488,7 +504,7 @@ DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) con const uint16_t *src = (const uint16_t *)GetData (offset_ptr, src_size); if (src) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { uint16_t *dst_pos = (uint16_t *)void_dst; uint16_t *dst_end = dst_pos + count; @@ -523,7 +539,7 @@ DataExtractor::GetU32 (offset_t *offset_ptr) const const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); if (data) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { val = ReadSwapInt32 (data); } @@ -551,7 +567,7 @@ DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) con const uint32_t *src = (const uint32_t *)GetData (offset_ptr, src_size); if (src) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { uint32_t *dst_pos = (uint32_t *)void_dst; uint32_t *dst_end = dst_pos + count; @@ -586,7 +602,7 @@ DataExtractor::GetU64 (offset_t *offset_ptr) const const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); if (data) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { val = ReadSwapInt64 (data); } @@ -612,7 +628,7 @@ DataExtractor::GetU64 (offset_t *offset_ptr, void *void_dst, uint32_t count) con const uint64_t *src = (const uint64_t *)GetData (offset_ptr, src_size); if (src) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { uint64_t *dst_pos = (uint64_t *)void_dst; uint64_t *dst_end = dst_pos + count; @@ -653,7 +669,7 @@ DataExtractor::GetMaxU32 (offset_t *offset_ptr, size_t byte_size) const case 2: return GetU16(offset_ptr); break; case 4: return GetU32(offset_ptr); break; default: - assert("GetMaxU32 unhandled case!" == NULL); + assert(false && "GetMaxU32 unhandled case!"); break; } return 0; @@ -679,7 +695,7 @@ DataExtractor::GetMaxU64 (offset_t *offset_ptr, size_t size) const case 4: return GetU32(offset_ptr); break; case 8: return GetU64(offset_ptr); break; default: - assert("GetMax64 unhandled case!" == NULL); + assert(false && "GetMax64 unhandled case!"); break; } return 0; @@ -695,7 +711,7 @@ DataExtractor::GetMaxU64_unchecked (offset_t *offset_ptr, size_t size) const case 4: return GetU32_unchecked (offset_ptr); break; case 8: return GetU64_unchecked (offset_ptr); break; default: - assert("GetMax64 unhandled case!" == NULL); + assert(false && "GetMax64 unhandled case!"); break; } return 0; @@ -711,7 +727,7 @@ DataExtractor::GetMaxS64 (offset_t *offset_ptr, size_t size) const case 4: return (int32_t)GetU32(offset_ptr); break; case 8: return (int64_t)GetU64(offset_ptr); break; default: - assert("GetMax64 unhandled case!" == NULL); + assert(false && "GetMax64 unhandled case!"); break; } return 0; @@ -760,7 +776,7 @@ DataExtractor::GetFloat (offset_t *offset_ptr) const const float_type *src = (const float_type *)GetData (offset_ptr, src_size); if (src) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { const uint8_t *src_data = (const uint8_t *)src; uint8_t *dst_data = (uint8_t *)&val; @@ -784,7 +800,7 @@ DataExtractor::GetDouble (offset_t *offset_ptr) const const float_type *src = (const float_type *)GetData (offset_ptr, src_size); if (src) { - if (m_byte_order != lldb::endian::InlHostByteOrder()) + if (m_byte_order != endian::InlHostByteOrder()) { const uint8_t *src_data = (const uint8_t *)src; uint8_t *dst_data = (uint8_t *)&val; @@ -805,9 +821,9 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const { long double val = 0.0; #if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) - *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), lldb::endian::InlHostByteOrder()); + *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), endian::InlHostByteOrder()); #else - *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), lldb::endian::InlHostByteOrder()); + *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), endian::InlHostByteOrder()); #endif return val; } @@ -824,12 +840,18 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const uint64_t DataExtractor::GetAddress (offset_t *offset_ptr) const { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif return GetMaxU64 (offset_ptr, m_addr_size); } uint64_t DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif return GetMaxU64_unchecked (offset_ptr, m_addr_size); } @@ -844,6 +866,9 @@ DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const uint64_t DataExtractor::GetPointer (offset_t *offset_ptr) const { +#ifdef LLDB_CONFIGURATION_DEBUG + assert (m_addr_size == 4 || m_addr_size == 8); +#endif return GetMaxU64 (offset_ptr, m_addr_size); } @@ -863,6 +888,9 @@ DataExtractor::GetGNUEHPointer (offset_t *offset_ptr, uint32_t eh_ptr_enc, lldb: uint64_t baseAddress = 0; uint64_t addressValue = 0; const uint32_t addr_size = GetAddressByteSize(); +#ifdef LLDB_CONFIGURATION_DEBUG + assert (addr_size == 4 || addr_size == 8); +#endif bool signExtendValue = false; // Decode the base part or adjust our offset @@ -1378,24 +1406,21 @@ DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::of return offset; } -static float half2float (uint16_t half) +static float +half2float (uint16_t half) { -#ifdef _MSC_VER - llvm_unreachable("half2float not implemented for MSVC"); -#else - union{ float f; uint32_t u;}u; + union { float f; uint32_t u; } u; int32_t v = (int16_t) half; - - if( 0 == (v & 0x7c00)) + + if (0 == (v & 0x7c00)) { u.u = v & 0x80007FFFU; return u.f * ldexpf(1, 125); } - + v <<= 13; u.u = v | 0x70000000U; return u.f * ldexpf(1, -112); -#endif } lldb::offset_t @@ -2012,6 +2037,12 @@ DataExtractor::Dump (Stream *s, s->PutChar('}'); break; + case eFormatVectorOfFloat16: + s->PutChar('{'); + offset = Dump (s, offset, eFormatFloat, 2, item_byte_size / 2, item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + case eFormatVectorOfFloat32: s->PutChar('{'); offset = Dump (s, offset, eFormatFloat, 4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0); diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index cd41e5d65103..d36800e20bc0 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -11,13 +11,12 @@ #include -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Type.h" #include "llvm/ADT/StringRef.h" #include "lldb/lldb-private.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/Module.h" +#include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" @@ -32,6 +31,7 @@ #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Expression/REPL.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Terminal.h" @@ -40,14 +40,12 @@ #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/OptionValueSInt64.h" #include "lldb/Interpreter/OptionValueString.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/VariableList.h" -#include "lldb/Target/CPPLanguageRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/TargetList.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SectionLoadList.h" @@ -88,9 +86,10 @@ GetDebuggerList() OptionEnumValueElement g_show_disassembly_enum_values[] = { - { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, - { Debugger::eStopDisassemblyTypeNoSource, "no-source", "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."}, + { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, + { Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", "Show disassembly when there is no debug information."}, + { Debugger::eStopDisassemblyTypeNoSource, "no-source", "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, NULL, NULL } }; @@ -105,6 +104,7 @@ g_language_enumerators[] = #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" +#define IS_OPTIMIZED "{${function.is-optimized} [opt]}" #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ "{, ${frame.pc}}"\ @@ -122,6 +122,7 @@ g_language_enumerators[] = #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ MODULE_WITH_FUNC\ FILE_AND_LINE\ + IS_OPTIMIZED\ "\\n" // Three parts to this disassembly format specification: @@ -150,7 +151,7 @@ g_properties[] = { "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." }, { "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, { "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." }, -{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, +{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoDebugInfo, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, { "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , NULL, NULL, "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 , NULL, NULL, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." }, @@ -158,6 +159,9 @@ g_properties[] = { "use-external-editor", OptionValue::eTypeBoolean , true, false, NULL, NULL, "Whether to use an external editor or not." }, { "use-color", OptionValue::eTypeBoolean , true, true , NULL, NULL, "Whether to use Ansi color codes or not." }, { "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, +{ "auto-indent", OptionValue::eTypeBoolean , true, true , NULL, NULL, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." }, +{ "print-decls", OptionValue::eTypeBoolean , true, true , NULL, NULL, "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 , NULL, NULL, "The tab size to use when indenting code in multi-line input mode (default: 4)." }, { "escape-non-printables", OptionValue::eTypeBoolean , true, true, NULL, NULL, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, { NULL, OptionValue::eTypeInvalid , true, 0 , NULL, NULL, NULL } }; @@ -179,6 +183,9 @@ enum ePropertyUseExternalEditor, ePropertyUseColor, ePropertyAutoOneLineSummaries, + ePropertyAutoIndent, + ePropertyPrintDecls, + ePropertyTabSize, ePropertyEscapeNonPrintables }; @@ -394,6 +401,49 @@ Debugger::GetEscapeNonPrintables () const return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); } +bool +Debugger::GetAutoIndent () const +{ + const uint32_t idx = ePropertyAutoIndent; + return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); +} + +bool +Debugger::SetAutoIndent (bool b) +{ + const uint32_t idx = ePropertyAutoIndent; + return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); +} + +bool +Debugger::GetPrintDecls () const +{ + const uint32_t idx = ePropertyPrintDecls; + return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, true); +} + +bool +Debugger::SetPrintDecls (bool b) +{ + const uint32_t idx = ePropertyPrintDecls; + return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b); +} + +uint32_t +Debugger::GetTabSize () const +{ + const uint32_t idx = ePropertyTabSize; + return m_collection_sp->GetPropertyAtIndexAsUInt64 (NULL, idx, g_properties[idx].default_uint_value); +} + +bool +Debugger::SetTabSize (uint32_t tab_size) +{ + const uint32_t idx = ePropertyTabSize; + return m_collection_sp->SetPropertyAtIndexAsUInt64 (NULL, idx, tab_size); +} + + #pragma mark Debugger //const DebuggerPropertiesSP & @@ -420,7 +470,11 @@ Debugger::Terminate () // Clear our master list of debugger objects Mutex::Locker locker (GetDebuggerListMutex ()); - GetDebuggerList().clear(); + auto& debuggers = GetDebuggerList(); + for (const auto& debugger: debuggers) + debugger->Clear(); + + debuggers.clear(); } void @@ -917,6 +971,12 @@ Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp) return m_input_reader_stack.IsTop (reader_sp); } +bool +Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type) +{ + return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type); +} + void Debugger::PrintAsync (const char *s, size_t len, bool is_stdout) { @@ -1681,6 +1741,12 @@ Debugger::IOHandlerThread (lldb::thread_arg_t arg) return NULL; } +bool +Debugger::HasIOHandlerThread() +{ + return m_io_handler_thread.IsJoinable(); +} + bool Debugger::StartIOHandlerThread() { @@ -1704,6 +1770,17 @@ Debugger::StopIOHandlerThread() } } +void +Debugger::JoinIOHandlerThread() +{ + if (HasIOHandlerThread()) + { + thread_result_t result; + m_io_handler_thread.Join(&result); + m_io_handler_thread = LLDB_INVALID_HOST_THREAD; + } +} + Target * Debugger::GetDummyTarget() { @@ -1724,3 +1801,52 @@ Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) return GetDummyTarget(); } +Error +Debugger::RunREPL (LanguageType language, const char *repl_options) +{ + Error err; + FileSpec repl_executable; + + if (language == eLanguageTypeUnknown) + { + std::set repl_languages; + + Language::GetLanguagesSupportingREPLs(repl_languages); + + if (repl_languages.size() == 1) + { + language = *repl_languages.begin(); + } + else if (repl_languages.size() == 0) + { + err.SetErrorStringWithFormat("LLDB isn't configured with support support for any REPLs."); + return err; + } + else + { + err.SetErrorStringWithFormat("Multiple possible REPL languages. Please specify a language."); + return err; + } + } + + Target *const target = nullptr; // passing in an empty target means the REPL must create one + + REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); + + if (!err.Success()) + { + return err; + } + + if (!repl_sp) + { + err.SetErrorStringWithFormat("couldn't find a REPL for %s", Language::GetNameForLanguageType(language)); + return err; + } + + repl_sp->SetCompilerOptions(repl_options); + repl_sp->RunLoop(); + + return err; +} + diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp index f96232fcceeb..bb5f106ca611 100644 --- a/source/Core/Disassembler.cpp +++ b/source/Core/Disassembler.cpp @@ -28,7 +28,6 @@ #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ExecutionContext.h" @@ -675,6 +674,13 @@ Instruction::DumpEmulation (const ArchSpec &arch) return false; } +bool +Instruction::HasDelaySlot () +{ + // Default is false. + return false; +} + OptionValueSP Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) { @@ -1264,7 +1270,7 @@ Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) : // If this is an arm variant that can only include thumb (T16, T32) // instructions, force the arch triple to be "thumbv.." instead of // "armv..." - if (arch.GetTriple().getArch() == llvm::Triple::arm + if ((arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) @@ -1319,6 +1325,13 @@ PseudoInstruction::DoesBranch () return false; } +bool +PseudoInstruction::HasDelaySlot () +{ + // This is NOT a valid question for a pseudo instruction. + return false; +} + size_t PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler, const lldb_private::DataExtractor &data, diff --git a/source/Core/DynamicLoader.cpp b/source/Core/DynamicLoader.cpp index ffd7425f5231..4d2824c5f334 100644 --- a/source/Core/DynamicLoader.cpp +++ b/source/Core/DynamicLoader.cpp @@ -119,16 +119,20 @@ DynamicLoader::GetTargetExecutable() } void -DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoader::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { - UpdateLoadedSectionsCommon(module, base_addr); + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } void -DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr) +DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, + addr_t base_addr, + bool base_addr_is_offset) { bool changed; - const bool base_addr_is_offset = true; module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed); } @@ -171,7 +175,10 @@ DynamicLoader::GetSectionListFromModule(const ModuleSP module) const } ModuleSP -DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) +DynamicLoader::LoadModuleAtAddress(const FileSpec &file, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { Target &target = m_process->GetTarget(); ModuleList &modules = target.GetImages(); @@ -180,27 +187,28 @@ DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, a ModuleSpec module_spec (file, target.GetArchitecture()); if ((module_sp = modules.FindFirstModule (module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset); } else if ((module_sp = target.GetSharedModule(module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset); } else { - // Try to fetch the load address of the file from the process. It can be different from the - // address reported by the linker in case of a file with fixed load address because the - // linker reports the bias between the load address specified in the file and the actual - // load address it loaded the file. - bool is_loaded; - lldb::addr_t load_addr; - Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); - if (error.Fail() || !is_loaded) - load_addr = base_addr; - - if ((module_sp = m_process->ReadModuleFromMemory(file, load_addr))) + if (base_addr_is_offset) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + // Try to fetch the load address of the file from the process as we need absolute load + // address to read the file out of the memory instead of a load bias. + bool is_loaded; + lldb::addr_t load_addr; + Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); + if (error.Success() && is_loaded) + base_addr = load_addr; + } + + if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) + { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); target.GetImages().AppendIfNeeded(module_sp); } } diff --git a/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp index 8349f54de4c7..9b6beeb8299a 100644 --- a/source/Core/EmulateInstruction.cpp +++ b/source/Core/EmulateInstruction.cpp @@ -635,17 +635,17 @@ EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info, return true; } - reg_num = reg_info->kinds[eRegisterKindGCC]; + reg_num = reg_info->kinds[eRegisterKindEHFrame]; if (reg_num != LLDB_INVALID_REGNUM) { - reg_kind = eRegisterKindGCC; + reg_kind = eRegisterKindEHFrame; return true; } - reg_num = reg_info->kinds[eRegisterKindGDB]; + reg_num = reg_info->kinds[eRegisterKindProcessPlugin]; if (reg_num != LLDB_INVALID_REGNUM) { - reg_kind = eRegisterKindGDB; + reg_kind = eRegisterKindProcessPlugin; return true; } return false; diff --git a/source/Core/Event.cpp b/source/Core/Event.cpp index bf5ff222a122..293a322257ef 100644 --- a/source/Core/Event.cpp +++ b/source/Core/Event.cpp @@ -147,7 +147,7 @@ EventDataBytes::Dump (Stream *s) const else if (m_bytes.size() > 0) { DataExtractor data; - data.SetData(&m_bytes[0], m_bytes.size(), lldb::endian::InlHostByteOrder()); + data.SetData(&m_bytes[0], m_bytes.size(), endian::InlHostByteOrder()); data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0); } } diff --git a/source/Core/FastDemangle.cpp b/source/Core/FastDemangle.cpp index 0f12af2783db..a27a2f1dbff1 100644 --- a/source/Core/FastDemangle.cpp +++ b/source/Core/FastDemangle.cpp @@ -161,7 +161,7 @@ public: /// the Itanium C++ ABI mangling specification as implemented by Clang /// /// @result Newly allocated null-terminated demangled name when demangling - /// is succesful, and nullptr when demangling fails. The caller is + /// is successful, and nullptr when demangling fails. The caller is /// responsible for freeing the allocated memory. char * diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp index e89d6c9cb4a9..804682f64bd3 100644 --- a/source/Core/FormatEntity.cpp +++ b/source/Core/FormatEntity.cpp @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringRef.h" - #include "lldb/Core/FormatEntity.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" + #include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Language.h" #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" @@ -21,7 +21,8 @@ #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/DataFormatters/FormatManager.h" -#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Host/FileSpec.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/Block.h" @@ -31,6 +32,7 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SectionLoadList.h" @@ -98,7 +100,8 @@ static FormatEntity::Entry::Definition g_function_child_entries[] = ENTRY ("line-offset" , FunctionLineOffset , UInt64), ENTRY ("pc-offset" , FunctionPCOffset , UInt64), ENTRY ("initial-function" , FunctionInitial , None), - ENTRY ("changed" , FunctionChanged , None) + ENTRY ("changed" , FunctionChanged , None), + ENTRY ("is-optimized" , FunctionIsOptimized , None) }; static FormatEntity::Entry::Definition g_line_child_entries[] = @@ -343,6 +346,7 @@ FormatEntity::Entry::TypeToCString (Type t) ENUM_TO_CSTR(FunctionPCOffset); ENUM_TO_CSTR(FunctionInitial); ENUM_TO_CSTR(FunctionChanged); + ENUM_TO_CSTR(FunctionIsOptimized); ENUM_TO_CSTR(LineEntryFile); ENUM_TO_CSTR(LineEntryLineNumber); ENUM_TO_CSTR(LineEntryStartAddress); @@ -530,7 +534,7 @@ ScanBracketedRange (llvm::StringRef subpath, int64_t& index_lower, int64_t& index_higher) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); close_bracket_index = llvm::StringRef::npos; const size_t open_bracket_index = subpath.find('['); if (open_bracket_index == llvm::StringRef::npos) @@ -667,7 +671,7 @@ ExpandIndexedExpression (ValueObject* valobj, StackFrame* frame, bool deref_pointer) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); const char* ptr_deref_format = "[%d]"; std::string ptr_deref_buffer(10,0); ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); @@ -728,7 +732,7 @@ DumpValue (Stream &s, if (valobj == NULL) return false; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); Format custom_format = eFormatInvalid; ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary; @@ -883,10 +887,10 @@ DumpValue (Stream &s, } // TODO use flags for these - const uint32_t type_info_flags = target->GetClangType().GetTypeInfo(NULL); + const uint32_t type_info_flags = target->GetCompilerType().GetTypeInfo(NULL); bool is_array = (type_info_flags & eTypeIsArray) != 0; bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; - bool is_aggregate = target->GetClangType().IsAggregateType(); + bool is_aggregate = target->GetCompilerType().IsAggregateType(); if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions { @@ -1302,6 +1306,8 @@ FormatEntity::Format (const Entry &entry, // Watch for the special "tid" format... if (entry.printf_format == "tid") { + // TODO(zturner): Rather than hardcoding this to be platform specific, it should be controlled by a + // setting and the default value of the setting can be different depending on the platform. Target &target = thread->GetProcess()->GetTarget(); ArchSpec arch (target.GetArchitecture ()); llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; @@ -1432,7 +1438,7 @@ FormatEntity::Format (const Entry &entry, StopInfoSP stop_info_sp = thread->GetStopInfo (); if (stop_info_sp && stop_info_sp->IsValid()) { - ClangExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); + ExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); if (expression_var_sp && expression_var_sp->GetValueObject()) { expression_var_sp->GetValueObject()->Dump(s); @@ -1524,8 +1530,7 @@ FormatEntity::Format (const Entry &entry, CompileUnit *cu = sc->comp_unit; if (cu) { - Language lang(cu->GetLanguage()); - const char *lang_name = lang.AsCString(); + const char *lang_name = Language::GetNameForLanguageType(cu->GetLanguage()); if (lang_name) { s.PutCString(lang_name); @@ -1648,187 +1653,267 @@ FormatEntity::Format (const Entry &entry, case Entry::Type::FunctionName: { - const char *name = NULL; + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; if (sc->function) - name = sc->function->GetName().AsCString (NULL); + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); else if (sc->symbol) - name = sc->symbol->GetName().AsCString (NULL); - if (name) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) { - s.PutCString(name); - - if (sc->block) + language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, + exe_ctx, + Language::FunctionNameRepresentation::eName, + ss); + } + if (language_plugin_handled) + { + s.PutCString(ss.GetData()); + return true; + } + else + { + const char *name = NULL; + if (sc->function) + name = sc->function->GetName().AsCString (NULL); + else if (sc->symbol) + name = sc->symbol->GetName().AsCString (NULL); + if (name) { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - if (inline_block) + s.PutCString(name); + + if (sc->block) { - const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) + Block *inline_block = sc->block->GetContainingInlinedBlock (); + if (inline_block) { - s.PutCString(" [inlined] "); - inline_info->GetName(sc->function->GetLanguage()).Dump(&s); + const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + { + s.PutCString(" [inlined] "); + inline_info->GetName(sc->function->GetLanguage()).Dump(&s); + } } } + return true; } - return true; } } return false; case Entry::Type::FunctionNameNoArgs: { - ConstString name; + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; if (sc->function) - name = sc->function->GetNameNoArguments(); + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); else if (sc->symbol) - name = sc->symbol->GetNameNoArguments(); - if (name) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) + { + language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, + exe_ctx, + Language::FunctionNameRepresentation::eNameWithNoArgs, + ss); + } + if (language_plugin_handled) { - s.PutCString(name.GetCString()); + s.PutCString(ss.GetData()); return true; } + else + { + ConstString name; + if (sc->function) + name = sc->function->GetNameNoArguments(); + else if (sc->symbol) + name = sc->symbol->GetNameNoArguments(); + if (name) + { + s.PutCString(name.GetCString()); + return true; + } + } } return false; case Entry::Type::FunctionNameWithArgs: { - // Print the function name with arguments in it + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; if (sc->function) + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); + else if (sc->symbol) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) { - ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; - const char *cstr = sc->function->GetName().AsCString (NULL); - if (cstr) + language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, + exe_ctx, + Language::FunctionNameRepresentation::eNameWithArgs, + ss); + } + if (language_plugin_handled) + { + s.PutCString(ss.GetData()); + return true; + } + else + { + // Print the function name with arguments in it + if (sc->function) { - const InlineFunctionInfo *inline_info = NULL; - VariableListSP variable_list_sp; - bool get_function_vars = true; - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - - if (inline_block) - { - get_function_vars = false; - inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - variable_list_sp = inline_block->GetBlockVariableList (true); - } - } - - if (get_function_vars) - { - variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); - } - - if (inline_info) - { - s.PutCString (cstr); - s.PutCString (" [inlined] "); - cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString(); - } - - VariableList args; - if (variable_list_sp) - variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); - if (args.GetSize() > 0) + ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL; + const char *cstr = sc->function->GetName().AsCString (NULL); + if (cstr) { - const char *open_paren = strchr (cstr, '('); - const char *close_paren = nullptr; - const char *generic = strchr(cstr, '<'); - // if before the arguments list begins there is a template sign - // then scan to the end of the generic args before you try to find - // the arguments list - if (generic && open_paren && generic < open_paren) + const InlineFunctionInfo *inline_info = NULL; + VariableListSP variable_list_sp; + bool get_function_vars = true; + if (sc->block) { - int generic_depth = 1; - ++generic; - for (; - *generic && generic_depth > 0; - generic++) + Block *inline_block = sc->block->GetContainingInlinedBlock (); + + if (inline_block) { - if (*generic == '<') - generic_depth++; - if (*generic == '>') - generic_depth--; + get_function_vars = false; + inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + variable_list_sp = inline_block->GetBlockVariableList (true); } - if (*generic) - open_paren = strchr(generic, '('); - else - open_paren = nullptr; } - if (open_paren) + + if (get_function_vars) { - if (IsToken (open_paren, "(anonymous namespace)")) - { - open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); - if (open_paren) - close_paren = strchr (open_paren, ')'); - } - else - close_paren = strchr (open_paren, ')'); + variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); } - - if (open_paren) - s.Write(cstr, open_paren - cstr + 1); - else + + if (inline_info) { s.PutCString (cstr); - s.PutChar ('('); + s.PutCString (" [inlined] "); + cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString(); } - const size_t num_args = args.GetSize(); - for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) + + VariableList args; + if (variable_list_sp) + variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); + if (args.GetSize() > 0) { - std::string buffer; - - VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); - ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); - const char *var_representation = nullptr; - const char *var_name = var_value_sp->GetName().GetCString(); - if (var_value_sp->GetClangType().IsAggregateType() && - DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) + const char *open_paren = strchr (cstr, '('); + const char *close_paren = nullptr; + const char *generic = strchr(cstr, '<'); + // if before the arguments list begins there is a template sign + // then scan to the end of the generic args before you try to find + // the arguments list + if (generic && open_paren && generic < open_paren) + { + int generic_depth = 1; + ++generic; + for (; + *generic && generic_depth > 0; + generic++) + { + if (*generic == '<') + generic_depth++; + if (*generic == '>') + generic_depth--; + } + if (*generic) + open_paren = strchr(generic, '('); + else + open_paren = nullptr; + } + if (open_paren) { - static StringSummaryFormat format(TypeSummaryImpl::Flags() - .SetHideItemNames(false) - .SetShowMembersOneLiner(true), - ""); - format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); - var_representation = buffer.c_str(); + if (IsToken (open_paren, "(anonymous namespace)")) + { + open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); + if (open_paren) + close_paren = strchr (open_paren, ')'); + } + else + close_paren = strchr (open_paren, ')'); } + + if (open_paren) + s.Write(cstr, open_paren - cstr + 1); else - var_representation = var_value_sp->GetValueAsCString(); - if (arg_idx > 0) - s.PutCString (", "); - if (var_value_sp->GetError().Success()) { - if (var_representation) - s.Printf ("%s=%s", var_name, var_representation); + s.PutCString (cstr); + s.PutChar ('('); + } + const size_t num_args = args.GetSize(); + for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) + { + std::string buffer; + + VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); + ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); + StreamString ss; + const char *var_representation = nullptr; + const char *var_name = var_value_sp->GetName().GetCString(); + if (var_value_sp->GetCompilerType().IsValid()) + { + if (var_value_sp && exe_scope->CalculateTarget()) + var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(exe_scope->CalculateTarget()->TargetProperties::GetPreferDynamicValue(), + exe_scope->CalculateTarget()->TargetProperties::GetEnableSyntheticValue()); + if (var_value_sp->GetCompilerType().IsAggregateType() && + DataVisualization::ShouldPrintAsOneLiner(*var_value_sp.get())) + { + static StringSummaryFormat format(TypeSummaryImpl::Flags() + .SetHideItemNames(false) + .SetShowMembersOneLiner(true), + ""); + format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); + var_representation = buffer.c_str(); + } + else + var_value_sp->DumpPrintableRepresentation(ss, + ValueObject::ValueObjectRepresentationStyle::eValueObjectRepresentationStyleSummary, + eFormatDefault, + ValueObject::PrintableRepresentationSpecialCases::ePrintableRepresentationSpecialCasesAllow, + false); + } + + if (ss.GetData() && ss.GetSize()) + var_representation = ss.GetData(); + if (arg_idx > 0) + s.PutCString (", "); + if (var_value_sp->GetError().Success()) + { + if (var_representation) + s.Printf ("%s=%s", var_name, var_representation); + else + s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); + } else - s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); + s.Printf ("%s=", var_name); } + + if (close_paren) + s.PutCString (close_paren); else - s.Printf ("%s=", var_name); + s.PutChar(')'); + } - - if (close_paren) - s.PutCString (close_paren); else - s.PutChar(')'); - + { + s.PutCString(cstr); + } + return true; } - else + } + else if (sc->symbol) + { + const char *cstr = sc->symbol->GetName().AsCString (NULL); + if (cstr) { s.PutCString(cstr); + return true; } - return true; - } - } - else if (sc->symbol) - { - const char *cstr = sc->symbol->GetName().AsCString (NULL); - if (cstr) - { - s.PutCString(cstr); - return true; } } } @@ -1870,6 +1955,16 @@ FormatEntity::Format (const Entry &entry, case Entry::Type::FunctionChanged: return function_changed == true; + case Entry::Type::FunctionIsOptimized: + { + bool is_optimized = false; + if (sc->function && sc->function->GetIsOptimized()) + { + is_optimized = true; + } + return is_optimized; + } + case Entry::Type::FunctionInitial: return initial_function == true; @@ -1976,7 +2071,7 @@ ParseEntry (const llvm::StringRef &format_str, switch (entry_def->type) { case FormatEntity::Entry::Type::ParentString: - entry.string = std::move(format_str.str()); + entry.string = format_str.str(); return error; // Success case FormatEntity::Entry::Type::ParentNumber: @@ -2026,7 +2121,7 @@ ParseEntry (const llvm::StringRef &format_str, { // Any value whose separator is a with a ':' means this value has a string argument // that needs to be stored in the entry (like "${script.var:modulename.function}") - entry.string = std::move(value.str()); + entry.string = value.str(); } else { @@ -2247,7 +2342,7 @@ FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint3 Entry entry; if (!variable_format.empty()) { - entry.printf_format = std::move(variable_format.str()); + entry.printf_format = variable_format.str(); // If the format contains a '%' we are going to assume this is // a printf style format. So if you want to format your thread ID @@ -2396,10 +2491,10 @@ FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef variable_name = llvm::StringRef(); variable_format = llvm::StringRef(); - const size_t paren_pos = format_str.find_first_of('}'); + const size_t paren_pos = format_str.find('}'); if (paren_pos != llvm::StringRef::npos) { - const size_t percent_pos = format_str.find_first_of('%'); + const size_t percent_pos = format_str.find('%'); if (percent_pos < paren_pos) { if (percent_pos > 0) @@ -2449,7 +2544,7 @@ MakeMatch (const llvm::StringRef &prefix, const char *suffix) { std::string match(prefix.str()); match.append(suffix); - return std::move(match); + return match; } static void @@ -2463,7 +2558,7 @@ AddMatches (const FormatEntity::Entry::Definition *def, { for (size_t i=0; ichildren[i].name)); else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0) @@ -2488,7 +2583,7 @@ FormatEntity::AutoComplete (const char *s, // Hitting TAB after $ at the end of the string add a "{" if (dollar_pos == str.size() - 1) { - std::string match = std::move(str.str()); + std::string match = str.str(); match.append("{"); matches.AppendString(std::move(match)); } @@ -2521,12 +2616,12 @@ FormatEntity::AutoComplete (const char *s, if (n > 0) { // "${thread.info" - matches.AppendString(std::move(MakeMatch (str, "."))); + matches.AppendString(MakeMatch(str, ".")); } else { // "${thread.id" - matches.AppendString(std::move(MakeMatch (str, "}"))); + matches.AppendString(MakeMatch (str, "}")); word_complete = true; } } diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index 0246778b0654..47d00e9184cf 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -7,9 +7,20 @@ // //===----------------------------------------------------------------------===// +// C Includes +#ifndef LLDB_DISABLE_CURSES +#include +#include +#endif +// C++ Includes +#if defined(__APPLE__) +#include +#endif #include +// Other libraries and framework includes +// Project includes #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/Debugger.h" @@ -28,10 +39,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/ThreadPlan.h" -#ifndef LLDB_DISABLE_CURSES -#include -#include -#endif + using namespace lldb; using namespace lldb_private; @@ -46,7 +54,6 @@ IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) : { } - IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type, const lldb::StreamFileSP &input_sp, @@ -71,10 +78,7 @@ IOHandler::IOHandler (Debugger &debugger, m_error_sp); } -IOHandler::~IOHandler() -{ -} - +IOHandler::~IOHandler() = default; int IOHandler::GetInputFD() @@ -136,7 +140,6 @@ IOHandler::GetOutputStreamFile() return m_output_sp; } - StreamFileSP & IOHandler::GetErrorStreamFile() { @@ -204,10 +207,7 @@ IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger, } - -IOHandlerConfirm::~IOHandlerConfirm () -{ -} +IOHandlerConfirm::~IOHandlerConfirm() = default; int IOHandlerConfirm::IOHandlerComplete (IOHandler &io_handler, @@ -334,11 +334,9 @@ IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler, break; } - return 0; } - IOHandlerEditline::IOHandlerEditline (Debugger &debugger, IOHandler::Type type, const char *editline_name, // Used for saving history files @@ -444,7 +442,6 @@ IOHandlerEditline::Deactivate () m_delegate.IOHandlerDeactivated(*this); } - bool IOHandlerEditline::GetLine (std::string &line, bool &interrupted) { @@ -619,7 +616,6 @@ IOHandlerEditline::GetContinuationPrompt () return m_continuation_prompt.c_str(); } - void IOHandlerEditline::SetContinuationPrompt (const char *p) { @@ -634,7 +630,6 @@ IOHandlerEditline::SetContinuationPrompt (const char *p) #endif } - void IOHandlerEditline::SetBaseLineNumber (uint32_t line) { @@ -824,6 +819,7 @@ type summary add -s "x=${var.x}, y=${var.y}" curses::Point type summary add -s "w=${var.width}, h=${var.height}" curses::Size type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect #endif + struct Point { int x; @@ -855,13 +851,13 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { printf ("(x=%i, y=%i)\n", x, y); } - }; bool operator == (const Point &lhs, const Point &rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } + bool operator != (const Point &lhs, const Point &rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; @@ -889,13 +885,13 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { printf ("(w=%i, h=%i)\n", width, height); } - }; bool operator == (const Size &lhs, const Size &rhs) { return lhs.width == rhs.width && lhs.height == rhs.height; } + bool operator != (const Size &lhs, const Size &rhs) { return lhs.width != rhs.width || lhs.height != rhs.height; @@ -942,6 +938,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect size.height -= h*2; origin.y += h; } + // Return a status bar rectangle which is the last line of // this rectangle. This rectangle will be modified to not // include the status bar area. @@ -1011,7 +1008,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect VerticalSplit (left_width, left, right); } - void VerticalSplit (int left_width, Rect &left, Rect &right) const { @@ -1035,6 +1031,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { return lhs.origin == rhs.origin && lhs.size == rhs.size; } + bool operator != (const Rect &lhs, const Rect &rhs) { return lhs.origin != rhs.origin || lhs.size != rhs.size; @@ -1064,9 +1061,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { public: virtual - ~WindowDelegate() - { - } + ~WindowDelegate() = default; virtual bool WindowDelegateDraw (Window &window, bool force) @@ -1098,9 +1093,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { public: HelpDialogDelegate (const char *text, KeyHelp *key_help_array); - + ~HelpDialogDelegate() override; - + bool WindowDelegateDraw (Window &window, bool force) override; @@ -1124,11 +1119,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect int m_first_visible_line; }; - class Window { public: - Window (const char *name) : m_name (name), m_window (NULL), @@ -1726,6 +1719,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { return m_name.c_str(); } + protected: std::string m_name; WINDOW *m_window; @@ -1747,8 +1741,8 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect class MenuDelegate { public: - virtual ~MenuDelegate() {} - + virtual ~MenuDelegate() = default; + virtual MenuActionResult MenuDelegateAction (Menu &menu) = 0; }; @@ -1772,10 +1766,8 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect const char *key_name, int key_value, uint64_t identifier); - - ~Menu () override - { - } + + ~Menu() override = default; const MenuDelegateSP & GetDelegate () const @@ -1912,7 +1904,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect return m_max_submenu_name_length + m_max_submenu_key_name_length + 8; } - uint64_t GetIdentifier() const { @@ -2223,7 +2214,7 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect { // Run the action on this menu in case we need to populate the // menu with dynamic content and also in case check marks, and - // any other menu decorations need to be caclulated + // any other menu decorations need to be calculated if (run_menu_sp->Action() == MenuActionResult::Quit) return eQuitApplication; @@ -2314,12 +2305,10 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect } else if (menu_type == Menu::Type::Separator) { - } return result; } - class Application { public: @@ -2496,7 +2485,6 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect } debugger.CancelForwardEvents (listener_sp); - } WindowSP & @@ -2520,11 +2508,9 @@ type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect FILE *m_in; FILE *m_out; }; - } // namespace curses - using namespace curses; struct Row @@ -2661,11 +2647,13 @@ class TreeDelegate { public: TreeDelegate() {} - virtual ~TreeDelegate() {} + virtual ~TreeDelegate() = default; + virtual void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) = 0; virtual void TreeDelegateGenerateChildren (TreeItem &item) = 0; virtual bool TreeDelegateItemSelected (TreeItem &item) = 0; // Return true if we need to update views }; + typedef std::shared_ptr TreeDelegateSP; class TreeItem @@ -2751,6 +2739,7 @@ public: { m_delegate.TreeDelegateItemSelected(*this); } + void CalculateRowIndexes (int &row_idx) { @@ -2944,7 +2933,6 @@ public: { m_identifier = identifier; } - void SetMightHaveChildren (bool b) @@ -2961,7 +2949,6 @@ protected: std::vector m_children; bool m_might_have_children; bool m_is_expanded; - }; class TreeWindowDelegate : public WindowDelegate @@ -3052,8 +3039,7 @@ public: return true; // Drawing handled } - - + const char * WindowDelegateGetHelpText () override { @@ -3125,6 +3111,7 @@ public: m_selected_item->ItemWasSelected (); } return eKeyHandled; + case KEY_DOWN: if (m_selected_row_idx + 1 < m_num_rows) { @@ -3191,7 +3178,6 @@ protected: int m_min_y; int m_max_x; int m_max_y; - }; class FrameTreeDelegate : public TreeDelegate @@ -3203,11 +3189,9 @@ public: FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}", m_format); } - - ~FrameTreeDelegate() override - { - } - + + ~FrameTreeDelegate() override = default; + void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override { @@ -3229,6 +3213,7 @@ public: } } } + void TreeDelegateGenerateChildren (TreeItem &item) override { @@ -3248,6 +3233,7 @@ public: } return false; } + protected: FormatEntity::Entry m_format; }; @@ -3264,11 +3250,9 @@ public: FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}", m_format); } - - ~ThreadTreeDelegate() override - { - } - + + ~ThreadTreeDelegate() override = default; + ProcessSP GetProcess () { @@ -3299,6 +3283,7 @@ public: } } } + void TreeDelegateGenerateChildren (TreeItem &item) override { @@ -3369,7 +3354,6 @@ protected: lldb::user_id_t m_tid; uint32_t m_stop_id; FormatEntity::Entry m_format; - }; class ThreadsTreeDelegate : public TreeDelegate @@ -3384,11 +3368,9 @@ public: FormatEntity::Parse("process ${process.id}{, name = ${process.name}}", m_format); } - - ~ThreadsTreeDelegate() override - { - } - + + ~ThreadsTreeDelegate() override = default; + ProcessSP GetProcess () { @@ -3460,7 +3442,6 @@ protected: Debugger &m_debugger; uint32_t m_stop_id; FormatEntity::Entry m_format; - }; class ValueObjectListDelegate : public WindowDelegate @@ -3490,10 +3471,8 @@ public: { SetValues (valobj_list); } - - ~ValueObjectListDelegate() override - { - } + + ~ValueObjectListDelegate() override = default; void SetValues (ValueObjectList &valobj_list) @@ -3586,7 +3565,6 @@ public: return g_source_view_key_help; } - HandleCharResult WindowDelegateHandleChar (Window &window, int c) override { @@ -3646,6 +3624,7 @@ public: if (m_selected_row_idx > 0) --m_selected_row_idx; return eKeyHandled; + case KEY_DOWN: if (m_selected_row_idx + 1 < m_num_rows) ++m_selected_row_idx; @@ -3784,6 +3763,7 @@ protected: return true; } + void DisplayRows (Window &window, std::vector &rows, @@ -3845,6 +3825,7 @@ protected: } return row_count; } + static Row * GetRowForRowIndexImpl (std::vector &rows, size_t &row_index) { @@ -3890,11 +3871,9 @@ public: m_frame_block (NULL) { } - - ~FrameVariablesWindowDelegate() override - { - } - + + ~FrameVariablesWindowDelegate() override = default; + const char * WindowDelegateGetHelpText () override { @@ -3924,7 +3903,6 @@ public: } } - ValueObjectList local_values; if (frame_block) { @@ -3964,7 +3942,6 @@ public: } return ValueObjectListDelegate::WindowDelegateDraw (window, force); - } protected: @@ -3972,7 +3949,6 @@ protected: Block *m_frame_block; }; - class RegistersWindowDelegate : public ValueObjectListDelegate { public: @@ -3982,10 +3958,8 @@ public: { } - ~RegistersWindowDelegate() - { - } - + ~RegistersWindowDelegate() override = default; + const char * WindowDelegateGetHelpText () override { @@ -4133,7 +4107,9 @@ CursesKeyToCString (int ch) case KEY_UNDO: return "undo key"; case KEY_MOUSE: return "Mouse event has occurred"; case KEY_RESIZE: return "Terminal resize event"; +#ifdef KEY_EVENT case KEY_EVENT: return "We were interrupted by an event"; +#endif case KEY_RETURN: return "return"; case ' ': return "space"; case '\t': return "tab"; @@ -4168,9 +4144,7 @@ HelpDialogDelegate::HelpDialogDelegate (const char *text, KeyHelp *key_help_arra } } -HelpDialogDelegate::~HelpDialogDelegate() -{ -} +HelpDialogDelegate::~HelpDialogDelegate() = default; bool HelpDialogDelegate::WindowDelegateDraw (Window &window, bool force) @@ -4235,6 +4209,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key) m_first_visible_line = 0; } break; + case KEY_NPAGE: case '.': if (m_first_visible_line + num_visible_lines < num_lines) @@ -4244,6 +4219,7 @@ HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key) m_first_visible_line = num_lines - num_visible_lines; } break; + default: done = true; break; @@ -4298,10 +4274,8 @@ public: m_debugger (debugger) { } - - ~ApplicationDelegate () - { - } + + ~ApplicationDelegate() override = default; bool WindowDelegateDraw (Window &window, bool force) override @@ -4330,8 +4304,7 @@ public: } return eKeyNotHandled; } - - + const char * WindowDelegateGetHelpText () override { @@ -4626,7 +4599,6 @@ protected: Debugger &m_debugger; }; - class StatusBarWindowDelegate : public WindowDelegate { public: @@ -4636,10 +4608,8 @@ public: FormatEntity::Parse("Thread: ${thread.id%tid}", m_format); } - - ~StatusBarWindowDelegate () - { - } + + ~StatusBarWindowDelegate() override = default; bool WindowDelegateDraw (Window &window, bool force) override @@ -4713,9 +4683,7 @@ public: { } - ~SourceFileWindowDelegate() override - { - } + ~SourceFileWindowDelegate() override = default; void Update (const SymbolContext &sc) @@ -5063,7 +5031,6 @@ public: } if (highlight_attr) window.AttributeOff(highlight_attr); - } else { @@ -5240,6 +5207,7 @@ public: return m_file_sp->GetNumLines(); return 0; } + size_t GetNumDisassemblyLines () const { @@ -5404,6 +5372,7 @@ public: } } return eKeyHandled; + case 'n': // 'n' == step over case 'N': // 'N' == step over instruction { @@ -5415,6 +5384,7 @@ public: } } return eKeyHandled; + case 's': // 's' == step into case 'S': // 'S' == step into instruction { @@ -5460,7 +5430,6 @@ protected: int m_min_y; int m_max_x; int m_max_y; - }; DisplayOptions ValueObjectListDelegate::g_options = { true }; @@ -5477,8 +5446,7 @@ IOHandlerCursesGUI::Activate () if (!m_app_ap) { m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE())); - - + // This is both a window and a menu delegate std::shared_ptr app_delegate_sp(new ApplicationDelegate(*m_app_ap, m_debugger)); @@ -5578,7 +5546,6 @@ IOHandlerCursesGUI::Activate () init_pair (3, COLOR_MAGENTA , COLOR_WHITE ); init_pair (4, COLOR_MAGENTA , COLOR_BLACK ); init_pair (5, COLOR_RED , COLOR_BLACK ); - } } @@ -5595,11 +5562,7 @@ IOHandlerCursesGUI::Run () SetIsDone(true); } - -IOHandlerCursesGUI::~IOHandlerCursesGUI () -{ - -} +IOHandlerCursesGUI::~IOHandlerCursesGUI() = default; void IOHandlerCursesGUI::Cancel () @@ -5612,10 +5575,9 @@ IOHandlerCursesGUI::Interrupt () return false; } - void IOHandlerCursesGUI::GotEOF() { } -#endif // #ifndef LLDB_DISABLE_CURSES +#endif // LLDB_DISABLE_CURSES diff --git a/source/Core/Language.cpp b/source/Core/Language.cpp deleted file mode 100644 index 1cc4b8a0dc9c..000000000000 --- a/source/Core/Language.cpp +++ /dev/null @@ -1,169 +0,0 @@ -//===-- Language.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/lldb-private.h" -#include "lldb/Core/Language.h" -#include "lldb/Core/Stream.h" -#include "llvm/ADT/STLExtras.h" -#include - -using namespace lldb; -using namespace lldb_private; - -#define ENUM_TO_DCSTREAM(x) case x: s->PutCString(#x); return - -struct LanguageStrings -{ - const char * names[3]; -}; - -static LanguageStrings -g_languages[] = -{ - { { "unknown" , NULL , NULL } }, - { { "c89" , NULL , "ISO C:1989" } }, - { { NULL , NULL , "K&R C" } }, - { { "ada83" , "Ada83" , "ISO Ada:1983" } }, - { { "c++" , "cxx" , "ISO C++:1998" } }, - { { "cobol74" , "Cobol74" , "ISO Cobol:1974" } }, - { { "cobol" , "Cobol85" , "ISO Cobol:1985." } }, - { { "f77" , "Fortran77" , "ISO Fortran 77." } }, - { { "f90" , "Fortran90" , "ISO Fortran 90" } }, - { { "pascal" , "Pascal83" , "ISO Pascal:1983" } }, - { { "modula2" , "Modula2" , "ISO Modula-2:1996" } }, - { { "java" , NULL , "Java" } }, - { { "c" , "C99" , "ISO C:1999" } }, - { { "ada" , "Ada95" , "ISO Ada:1995" } }, - { { "f95" , "Fortran95" , "ISO Fortran 95" } }, - { { "PLI" , NULL , "ANSI PL/I:1976" } }, - { { "objc" , NULL , "Objective-C" } }, - { { "objc++" , NULL , "Objective-C++" } }, - { { "upc" , NULL , "Unified Parallel C" } }, - { { "d" , NULL , "D" } }, - { { "python" , NULL , "Python" } }, - { { "opencl" , "OpenCL" , "OpenCL" } }, - { { "go" , "Go" , "Go" } }, - { { "modula3" , "Modula3" , "Modula 3" } }, - { { "haskell" , "Haskell" , "Haskell" } }, - { { "c++03" , "C_plus_plus_03" , "ISO C++:2003" } }, - { { "c++11" , "C_plus_plus_11" , "ISO C++:2011" } }, - { { "ocaml" , "OCaml" , "OCaml" } }, - { { "rust" , "Rust" , "Rust" } }, - { { "c11" , "C11" , "ISO C:2011" } }, - { { "swift" , "Swift" , "Swift" } }, - { { "julia" , "Julia" , "Julia" } }, - { { "dylan" , "Dylan" , "Dylan" } }, - { { "c++14" , "C_plus_plus_14" , "ISO C++:2014" } }, - { { "f03" , "Fortran03" , "ISO Fortran 2003" } }, - { { "f08" , "Fortran08" , "ISO Fortran 2008" } }, - // Vendor Extensions - { { "mipsassem" , "Mips_Assembler" , "Mips Assembler" } }, - { { "renderscript" , "RenderScript" , "RenderScript" } } -}; - -static const size_t g_num_languages = llvm::array_lengthof(g_languages); - -Language::Language(LanguageType language) : - m_language (language) -{ -} - -Language::~Language() -{ -} - -LanguageType -Language::GetLanguage() const -{ - return m_language; -} - -void -Language::Clear () -{ - m_language = eLanguageTypeUnknown; -} - -void -Language::SetLanguage(LanguageType language) -{ - m_language = language; -} - -bool -Language::SetLanguageFromCString(const char *language_cstr) -{ - size_t i, desc_idx; - const char *name; - - // First check the most common name for the languages - for (desc_idx=lldb::eDescriptionLevelBrief; desc_idxPutCString(lang_cstr); - else - s->Printf("Language(language = 0x%4.4x)", m_language); -} - - - - -Stream& -lldb_private::operator << (Stream& s, const Language& language) -{ - language.Dump(&s); - return s; -} - diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp index 6acd50eec76a..8d415bdc0e77 100644 --- a/source/Core/Log.cpp +++ b/source/Core/Log.cpp @@ -143,6 +143,7 @@ Log::VAPrintf(const char *format, va_list args) std::string back_trace; llvm::raw_string_ostream stream(back_trace); llvm::sys::PrintStackTrace(stream); + stream.flush(); header.PutCString(back_trace.c_str()); } @@ -449,7 +450,7 @@ Log::DisableAllLogChannels (Stream *feedback_strm) { CallbackMap &callback_map = GetCallbackMap (); CallbackMapIter pos, end = callback_map.end(); - const char *categories[1] = {NULL}; + const char *categories[] = {"all", nullptr}; for (pos = callback_map.begin(); pos != end; ++pos) pos->second.disable (categories, feedback_strm); diff --git a/source/Core/Logging.cpp b/source/Core/Logging.cpp index 412536adbb34..d08d833ee469 100644 --- a/source/Core/Logging.cpp +++ b/source/Core/Logging.cpp @@ -148,6 +148,7 @@ lldb_private::DisableLog (const char **categories, Stream *feedback_strm) else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS; else if (0 == ::strcasecmp(arg, "jit")) flag_bits &= ~LIBLLDB_LOG_JIT_LOADER; else if (0 == ::strcasecmp(arg, "language")) flag_bits &= ~LIBLLDB_LOG_LANGUAGE; + else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS; else { feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg); @@ -224,6 +225,7 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const ch else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits |= LIBLLDB_LOG_WATCHPOINTS; else if (0 == ::strcasecmp(arg, "jit")) flag_bits |= LIBLLDB_LOG_JIT_LOADER; else if (0 == ::strcasecmp(arg, "language")) flag_bits |= LIBLLDB_LOG_LANGUAGE; + else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits |= LIBLLDB_LOG_DATAFORMATTERS; else { feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); @@ -254,6 +256,7 @@ lldb_private::ListLogCategories (Stream *strm) " dyld - log shared library related activities\n" " events - log broadcaster, listener and event queue activities\n" " expr - log expressions\n" + " formatters - log data formatters related activities\n" " host - log host activities\n" " jit - log JIT events in the target\n" " language - log language runtime events\n" diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index a1916fe913c4..bdc710c8f8e1 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -38,7 +38,8 @@ #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" -#include "lldb/Target/CPPLanguageRuntime.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include #include #include @@ -94,11 +95,12 @@ get_demangled_name_without_arguments (ConstString mangled, ConstString demangled mangled_name_cstr[2] != 'G' && // avoid guard variables mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back) { - CPPLanguageRuntime::MethodName cxx_method (demangled); - if (!cxx_method.GetBasename().empty() && !cxx_method.GetContext().empty()) + CPlusPlusLanguage::MethodName cxx_method (demangled); + if (!cxx_method.GetBasename().empty()) { - std::string shortname = cxx_method.GetContext().str(); - shortname += "::"; + std::string shortname; + if (!cxx_method.GetContext().empty()) + shortname = cxx_method.GetContext().str() + "::"; shortname += cxx_method.GetBasename().str(); ConstString result(shortname.c_str()); g_most_recent_mangled_to_name_sans_args.first = mangled; @@ -360,6 +362,9 @@ Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType languag ConstString Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const { + if (preference == ePreferMangled && m_mangled) + return m_mangled; + ConstString demangled = GetDemangledName(language); if (preference == ePreferDemangledWithoutArguments) @@ -374,12 +379,7 @@ Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preferenc return demangled; return m_mangled; } - else - { - if (m_mangled) - return m_mangled; - return demangled; - } + return demangled; } //---------------------------------------------------------------------- @@ -425,6 +425,14 @@ Mangled::MemorySize () const return m_mangled.MemorySize() + m_demangled.MemorySize(); } +//---------------------------------------------------------------------- +// We "guess" the language because we can't determine a symbol's language +// from it's name. For example, a Pascal symbol can be mangled using the +// C++ Itanium scheme, and defined in a compilation unit within the same +// module as other C++ units. In addition, different targets could have +// different ways of mangling names from a given language, likewise the +// compilation units within those targets. +//---------------------------------------------------------------------- lldb::LanguageType Mangled::GuessLanguage () const { @@ -433,11 +441,14 @@ Mangled::GuessLanguage () const { if (GetDemangledName(lldb::eLanguageTypeUnknown)) { - if (cstring_is_mangled(mangled.GetCString())) + const char *mangled_name = mangled.GetCString(); + if (CPlusPlusLanguage::IsCPPMangledName(mangled_name)) return lldb::eLanguageTypeC_plus_plus; + else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name)) + return lldb::eLanguageTypeObjC; } } - return lldb::eLanguageTypeUnknown; + return lldb::eLanguageTypeUnknown; } //---------------------------------------------------------------------- diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index eb0359d02d5b..833540e1a309 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" @@ -23,17 +24,19 @@ #include "lldb/Host/Symbols.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Target/CPPLanguageRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" -#include "lldb/Symbol/SymbolFile.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "lldb/Symbol/TypeMap.h" #include "Plugins/ObjectFile/JIT/ObjectFileJIT.h" @@ -146,13 +149,12 @@ Module::Module (const ModuleSpec &module_spec) : m_object_mod_time (), m_objfile_sp (), m_symfile_ap (), - m_ast (new ClangASTContext), + m_type_system_map(), m_source_mappings (), m_sections_ap(), m_did_load_objfile (false), m_did_load_symbol_vendor (false), m_did_parse_uuid (false), - m_did_init_ast (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -250,13 +252,12 @@ Module::Module(const FileSpec& file_spec, m_object_mod_time (), m_objfile_sp (), m_symfile_ap (), - m_ast (new ClangASTContext), + m_type_system_map(), m_source_mappings (), m_sections_ap(), m_did_load_objfile (false), m_did_load_symbol_vendor (false), m_did_parse_uuid (false), - m_did_init_ast (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -296,13 +297,12 @@ Module::Module () : m_object_mod_time (), m_objfile_sp (), m_symfile_ap (), - m_ast (new ClangASTContext), + m_type_system_map(), m_source_mappings (), m_sections_ap(), m_did_load_objfile (false), m_did_load_symbol_vendor (false), m_did_parse_uuid (false), - m_did_init_ast (false), m_file_has_changed (false), m_first_file_changed_log (false) { @@ -399,52 +399,27 @@ Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t hea const lldb_private::UUID& Module::GetUUID() { - Mutex::Locker locker (m_mutex); - if (m_did_parse_uuid == false) + if (m_did_parse_uuid.load() == false) { - ObjectFile * obj_file = GetObjectFile (); - - if (obj_file != NULL) + Mutex::Locker locker (m_mutex); + if (m_did_parse_uuid.load() == false) { - obj_file->GetUUID(&m_uuid); - m_did_parse_uuid = true; + ObjectFile * obj_file = GetObjectFile (); + + if (obj_file != NULL) + { + obj_file->GetUUID(&m_uuid); + m_did_parse_uuid = true; + } } } return m_uuid; } -ClangASTContext & -Module::GetClangASTContext () +TypeSystem * +Module::GetTypeSystemForLanguage (LanguageType language) { - Mutex::Locker locker (m_mutex); - if (m_did_init_ast == false) - { - ObjectFile * objfile = GetObjectFile(); - ArchSpec object_arch; - if (objfile && objfile->GetArchitecture(object_arch)) - { - m_did_init_ast = true; - - // LLVM wants this to be set to iOS or MacOSX; if we're working on - // a bare-boards type image, change the triple for llvm's benefit. - if (object_arch.GetTriple().getVendor() == llvm::Triple::Apple - && object_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) - { - if (object_arch.GetTriple().getArch() == llvm::Triple::arm || - object_arch.GetTriple().getArch() == llvm::Triple::aarch64 || - object_arch.GetTriple().getArch() == llvm::Triple::thumb) - { - object_arch.GetTriple().setOS(llvm::Triple::IOS); - } - else - { - object_arch.GetTriple().setOS(llvm::Triple::MacOSX); - } - } - m_ast->SetArchitecture (object_arch); - } - } - return *m_ast; + return m_type_system_map.GetTypeSystemForLanguage(language, this, true); } void @@ -706,14 +681,14 @@ Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t li size_t Module::FindGlobalVariables (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, VariableList& variables) { SymbolVendor *symbols = GetSymbolVendor (); if (symbols) - return symbols->FindGlobalVariables(name, namespace_decl, append, max_matches, variables); + return symbols->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables); return 0; } @@ -756,7 +731,7 @@ Module::FindCompileUnits (const FileSpec &path, size_t Module::FindFunctions (const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_symbols, bool include_inlines, @@ -778,6 +753,7 @@ Module::FindFunctions (const ConstString &name, bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, + eLanguageTypeUnknown, // TODO: add support lookup_name, lookup_name_type_mask, match_name_after_lookup); @@ -785,7 +761,7 @@ Module::FindFunctions (const ConstString &name, if (symbols) { symbols->FindFunctions(lookup_name, - namespace_decl, + parent_decl_ctx, lookup_name_type_mask, include_inlines, append, @@ -825,7 +801,7 @@ Module::FindFunctions (const ConstString &name, { if (symbols) { - symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list); + symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list); // Now check our symbol table for symbols that are code symbols if requested if (include_symbols) @@ -943,17 +919,17 @@ Module::FindAddressesForLine (const lldb::TargetSP target_sp, size_t Module::FindTypes_Impl (const SymbolContext& sc, const ConstString &name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, - TypeList& types) + TypeMap& types) { Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); if (sc.module_sp.get() == NULL || sc.module_sp.get() == this) { SymbolVendor *symbols = GetSymbolVendor (); if (symbols) - return symbols->FindTypes(sc, name, namespace_decl, append, max_matches, types); + return symbols->FindTypes(sc, name, parent_decl_ctx, append, max_matches, types); } return 0; } @@ -961,12 +937,16 @@ Module::FindTypes_Impl (const SymbolContext& sc, size_t Module::FindTypesInNamespace (const SymbolContext& sc, const ConstString &type_name, - const ClangNamespaceDecl *namespace_decl, + const CompilerDeclContext *parent_decl_ctx, size_t max_matches, TypeList& type_list) { const bool append = true; - return FindTypes_Impl(sc, type_name, namespace_decl, append, max_matches, type_list); + TypeMap types_map; + size_t num_types = FindTypes_Impl(sc, type_name, parent_decl_ctx, append, max_matches, types_map); + if (num_types > 0) + sc.SortTypeList(types_map, type_list); + return num_types; } lldb::TypeSP @@ -995,6 +975,7 @@ Module::FindTypes (const SymbolContext& sc, std::string type_basename; const bool append = true; TypeClass type_class = eTypeClassAny; + TypeMap typesmap; if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename, type_class)) { // Check if "name" starts with "::" which means the qualified type starts @@ -1008,10 +989,10 @@ Module::FindTypes (const SymbolContext& sc, exact_match = true; } ConstString type_basename_const_str (type_basename.c_str()); - if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, types)) + if (FindTypes_Impl(sc, type_basename_const_str, NULL, append, max_matches, typesmap)) { - types.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); - num_matches = types.GetSize(); + typesmap.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); + num_matches = typesmap.GetSize(); } } else @@ -1021,32 +1002,35 @@ Module::FindTypes (const SymbolContext& sc, { // The "type_name_cstr" will have been modified if we have a valid type class // prefix (like "struct", "class", "union", "typedef" etc). - FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, types); - types.RemoveMismatchedTypes (type_class); - num_matches = types.GetSize(); + FindTypes_Impl(sc, ConstString(type_name_cstr), NULL, append, max_matches, typesmap); + typesmap.RemoveMismatchedTypes (type_class); + num_matches = typesmap.GetSize(); } else { - num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, types); + num_matches = FindTypes_Impl(sc, name, NULL, append, max_matches, typesmap); } } - + if (num_matches > 0) + sc.SortTypeList(typesmap, types); return num_matches; - } SymbolVendor* Module::GetSymbolVendor (bool can_create, lldb_private::Stream *feedback_strm) { - Mutex::Locker locker (m_mutex); - if (m_did_load_symbol_vendor == false && can_create) + if (m_did_load_symbol_vendor.load() == false) { - ObjectFile *obj_file = GetObjectFile (); - if (obj_file != NULL) + Mutex::Locker locker (m_mutex); + if (m_did_load_symbol_vendor.load() == false && can_create) { - Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); - m_did_load_symbol_vendor = true; + ObjectFile *obj_file = GetObjectFile (); + if (obj_file != NULL) + { + Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); + m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); + m_did_load_symbol_vendor = true; + } } } return m_symfile_ap.get(); @@ -1287,37 +1271,40 @@ Module::GetObjectName() const ObjectFile * Module::GetObjectFile() { - Mutex::Locker locker (m_mutex); - if (m_did_load_objfile == false) + if (m_did_load_objfile.load() == false) { - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString("")); - DataBufferSP data_sp; - lldb::offset_t data_offset = 0; - const lldb::offset_t file_size = m_file.GetByteSize(); - if (file_size > m_object_offset) + Mutex::Locker locker (m_mutex); + if (m_did_load_objfile.load() == false) { - m_did_load_objfile = true; - m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(), - &m_file, - m_object_offset, - file_size - m_object_offset, - data_sp, - data_offset); - if (m_objfile_sp) + Timer scoped_timer(__PRETTY_FUNCTION__, + "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString("")); + DataBufferSP data_sp; + lldb::offset_t data_offset = 0; + const lldb::offset_t file_size = m_file.GetByteSize(); + if (file_size > m_object_offset) { - // 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. 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); - } - else - { - ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str()); + m_did_load_objfile = true; + m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(), + &m_file, + m_object_offset, + file_size - m_object_offset, + data_sp, + data_offset); + if (m_objfile_sp) + { + // Once we get the object file, update our module with the object file's + // architecture since it might differ in vendor/os if some parts were + // unknown. 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); + } + else + { + ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str()); + } } } } @@ -1487,6 +1474,9 @@ Module::SetSymbolFileFileSpec (const FileSpec &file) // we don't have to do anything. return; } + + // Cleare the current symtab as we are going to replace it with a new one + obj_file->ClearSymtab(); // The symbol file might be a directory bundle ("/tmp/a.out.dSYM") instead // of a full path to the symbol file within the bundle @@ -1680,7 +1670,8 @@ Module::MatchesModuleSpec (const ModuleSpec &module_ref) const FileSpec &file_spec = module_ref.GetFileSpec(); if (file_spec) { - if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory())) + if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory()) && + !FileSpec::Equal (file_spec, m_platform_file, (bool)file_spec.GetDirectory())) return false; } @@ -1739,6 +1730,7 @@ Module::GetVersion (uint32_t *versions, uint32_t num_versions) void Module::PrepareForFunctionNameLookup (const ConstString &name, uint32_t name_type_mask, + LanguageType language, ConstString &lookup_name, uint32_t &lookup_name_type_mask, bool &match_name_after_lookup) @@ -1752,20 +1744,28 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, if (name_type_mask & eFunctionNameTypeAuto) { - if (CPPLanguageRuntime::IsCPPMangledName (name_cstr)) + if (CPlusPlusLanguage::IsCPPMangledName (name_cstr)) lookup_name_type_mask = eFunctionNameTypeFull; - else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr)) + else if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCMethodName (name_cstr)) lookup_name_type_mask = eFunctionNameTypeFull; + else if (Language::LanguageIsC(language)) + { + lookup_name_type_mask = eFunctionNameTypeFull; + } else { - if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr)) + if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCSelector(name_cstr)) lookup_name_type_mask |= eFunctionNameTypeSelector; - CPPLanguageRuntime::MethodName cpp_method (name); + CPlusPlusLanguage::MethodName cpp_method (name); basename = cpp_method.GetBasename(); if (basename.empty()) { - if (CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename)) + if (CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename)) lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); else lookup_name_type_mask |= eFunctionNameTypeFull; @@ -1783,7 +1783,7 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, { // If they've asked for a CPP method or function name and it can't be that, we don't // even need to search for CPP methods or names. - CPPLanguageRuntime::MethodName cpp_method (name); + CPlusPlusLanguage::MethodName cpp_method (name); if (cpp_method.IsValid()) { basename = cpp_method.GetBasename(); @@ -1801,13 +1801,13 @@ Module::PrepareForFunctionNameLookup (const ConstString &name, { // If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can. // If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later. - CPPLanguageRuntime::ExtractContextAndIdentifier (name_cstr, context, basename); + CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); } } if (lookup_name_type_mask & eFunctionNameTypeSelector) { - if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr)) + if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) { lookup_name_type_mask &= ~(eFunctionNameTypeSelector); if (lookup_name_type_mask == eFunctionNameTypeNone) diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp index 669b3d9274cc..75b2ca11103a 100644 --- a/source/Core/ModuleList.cpp +++ b/source/Core/ModuleList.cpp @@ -22,7 +22,6 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/Symbols.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/VariableList.h" @@ -70,7 +69,7 @@ ModuleList::operator= (const ModuleList& rhs) // That's probably me nit-picking, but in theoretical situation: // // * that two threads A B and - // * two ModuleList's x y do opposite assignemnts ie.: + // * two ModuleList's x y do opposite assignments ie.: // // in thread A: | in thread B: // x = y; | y = x; @@ -372,6 +371,7 @@ ModuleList::FindFunctions (const ConstString &name, uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, + eLanguageTypeUnknown, // TODO: add support lookup_name, lookup_name_type_mask, match_name_after_lookup); @@ -436,6 +436,7 @@ ModuleList::FindFunctionSymbols (const ConstString &name, uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, + eLanguageTypeUnknown, // TODO: add support lookup_name, lookup_name_type_mask, match_name_after_lookup); @@ -682,7 +683,7 @@ ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool na { // 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 comparisong will always be true (valid_module_ptr != NULL). + // the comparison will always be true (valid_module_ptr != NULL). if (sc.module_sp.get() != (*pos).get()) total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, types); @@ -988,18 +989,31 @@ ModuleList::GetSharedModule // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) + { module_sp.reset(); + } else { - if (did_create_ptr) - *did_create_ptr = true; + if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) + { + module_sp.reset(); + } + else + { + if (did_create_ptr) + { + *did_create_ptr = true; + } - shared_module_list.ReplaceEquivalent(module_sp); - return error; + shared_module_list.ReplaceEquivalent(module_sp); + return error; + } } } else + { module_sp.reset(); + } if (module_search_paths_ptr) { @@ -1023,18 +1037,29 @@ ModuleList::GetSharedModule // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) + { module_sp.reset(); + } else { - if (did_create_ptr) - *did_create_ptr = true; - - shared_module_list.ReplaceEquivalent(module_sp); - return Error(); + if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) + { + module_sp.reset(); + } + else + { + if (did_create_ptr) + *did_create_ptr = true; + + shared_module_list.ReplaceEquivalent(module_sp); + return Error(); + } } } else + { module_sp.reset(); + } } } @@ -1044,19 +1069,19 @@ ModuleList::GetSharedModule // Fixup the incoming path in case the path points to a valid file, yet // the arch or UUID (if one was passed in) don't match. - FileSpec file_spec = Symbols::LocateExecutableObjectFile (module_spec); + ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec); // Don't look for the file if it appears to be the same one we already // checked for above... - if (file_spec != module_file_spec) + if (located_binary_modulespec.GetFileSpec() != module_file_spec) { - if (!file_spec.Exists()) + if (!located_binary_modulespec.GetFileSpec().Exists()) { - file_spec.GetPath(path, sizeof(path)); + 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 (file_spec.Exists()) + if (located_binary_modulespec.GetFileSpec().Exists()) { std::string uuid_str; if (uuid_ptr && uuid_ptr->IsValid()) @@ -1084,8 +1109,9 @@ ModuleList::GetSharedModule // function is actively working on it by doing an extra lock on the // global mutex list. ModuleSpec platform_module_spec(module_spec); - platform_module_spec.GetFileSpec() = file_spec; - platform_module_spec.GetPlatformFileSpec() = file_spec; + platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec(); + platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec(); + platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec(); ModuleList matching_module_list; if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) { @@ -1095,7 +1121,7 @@ ModuleList::GetSharedModule // then we should make sure the modification time hasn't changed! if (platform_module_spec.GetUUIDPtr() == NULL) { - TimeValue file_spec_mod_time(file_spec.GetModificationTime()); + TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime()); if (file_spec_mod_time.IsValid()) { if (file_spec_mod_time != module_sp->GetModificationTime()) @@ -1117,16 +1143,23 @@ ModuleList::GetSharedModule // By getting the object file we can guarantee that the architecture matches if (module_sp && module_sp->GetObjectFile()) { - if (did_create_ptr) - *did_create_ptr = true; + if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) + { + module_sp.reset(); + } + else + { + if (did_create_ptr) + *did_create_ptr = true; - shared_module_list.ReplaceEquivalent(module_sp); + shared_module_list.ReplaceEquivalent(module_sp); + } } else { - file_spec.GetPath(path, sizeof(path)); + located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); - if (file_spec) + if (located_binary_modulespec.GetFileSpec()) { if (arch.IsValid()) error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp index 73f5f85923c6..89eea2624cec 100644 --- a/source/Core/Opcode.cpp +++ b/source/Core/Opcode.cpp @@ -82,7 +82,7 @@ Opcode::GetDataByteOrder () const case Opcode::eType16: case Opcode::eType16_2: case Opcode::eType32: - case Opcode::eType64: return lldb::endian::InlHostByteOrder(); + case Opcode::eType64: return endian::InlHostByteOrder(); case Opcode::eTypeBytes: break; } diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp index e34b7fc3b17d..a90b57678b7a 100644 --- a/source/Core/PluginManager.cpp +++ b/source/Core/PluginManager.cpp @@ -771,16 +771,18 @@ PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const ConstStri struct OperatingSystemInstance { - OperatingSystemInstance() : - name(), - description(), - create_callback(NULL) + OperatingSystemInstance () : + name (), + description (), + create_callback (nullptr), + debugger_init_callback (nullptr) { } ConstString name; std::string description; OperatingSystemCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector OperatingSystemInstances; @@ -800,9 +802,9 @@ GetOperatingSystemInstances () } bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - OperatingSystemCreateInstance create_callback) +PluginManager::RegisterPlugin(const ConstString &name, const char *description, + OperatingSystemCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { if (create_callback) { @@ -812,6 +814,7 @@ PluginManager::RegisterPlugin (const ConstString &name, if (description && description[0]) instance.description = description; instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; Mutex::Locker locker (GetOperatingSystemMutex ()); GetOperatingSystemInstances ().push_back (instance); } @@ -868,6 +871,111 @@ PluginManager::GetOperatingSystemCreateCallbackForPluginName (const ConstString } +#pragma mark Language + + +struct LanguageInstance +{ + LanguageInstance() : + name(), + description(), + create_callback(NULL) + { + } + + ConstString name; + std::string description; + LanguageCreateInstance create_callback; +}; + +typedef std::vector LanguageInstances; + +static Mutex & +GetLanguageMutex () +{ + static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static LanguageInstances & +GetLanguageInstances () +{ + static LanguageInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin +( + const ConstString &name, + const char *description, + LanguageCreateInstance create_callback + ) +{ + if (create_callback) + { + LanguageInstance instance; + assert ((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + Mutex::Locker locker (GetLanguageMutex ()); + GetLanguageInstances ().push_back (instance); + } + return false; +} + +bool +PluginManager::UnregisterPlugin (LanguageCreateInstance create_callback) +{ + if (create_callback) + { + Mutex::Locker locker (GetLanguageMutex ()); + LanguageInstances &instances = GetLanguageInstances (); + + LanguageInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (pos->create_callback == create_callback) + { + instances.erase(pos); + return true; + } + } + } + return false; +} + +LanguageCreateInstance +PluginManager::GetLanguageCreateCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetLanguageMutex ()); + LanguageInstances &instances = GetLanguageInstances (); + if (idx < instances.size()) + return instances[idx].create_callback; + return NULL; +} + +LanguageCreateInstance +PluginManager::GetLanguageCreateCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetLanguageMutex ()); + LanguageInstances &instances = GetLanguageInstances (); + + LanguageInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->create_callback; + } + } + return NULL; +} + + #pragma mark LanguageRuntime @@ -1764,6 +1872,110 @@ PluginManager::GetProcessCreateCallbackForPluginName (const ConstString &name) return NULL; } +#pragma mark ScriptInterpreter + +struct ScriptInterpreterInstance +{ + ScriptInterpreterInstance() + : name() + , language(lldb::eScriptLanguageNone) + , description() + , create_callback(NULL) + { + } + + ConstString name; + lldb::ScriptLanguage language; + std::string description; + ScriptInterpreterCreateInstance create_callback; +}; + +typedef std::vector ScriptInterpreterInstances; + +static Mutex & +GetScriptInterpreterMutex() +{ + static Mutex g_instances_mutex(Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static ScriptInterpreterInstances & +GetScriptInterpreterInstances() +{ + static ScriptInterpreterInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_language, + ScriptInterpreterCreateInstance create_callback) +{ + if (!create_callback) + return false; + ScriptInterpreterInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.language = script_language; + Mutex::Locker locker(GetScriptInterpreterMutex()); + GetScriptInterpreterInstances().push_back(instance); + return false; +} + +bool +PluginManager::UnregisterPlugin(ScriptInterpreterCreateInstance create_callback) +{ + if (!create_callback) + return false; + Mutex::Locker locker(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + + ScriptInterpreterInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) + { + if (pos->create_callback != create_callback) + continue; + + instances.erase(pos); + return true; + } + return false; +} + +ScriptInterpreterCreateInstance +PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) +{ + Mutex::Locker locker(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; +} + +lldb::ScriptInterpreterSP +PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) +{ + Mutex::Locker locker(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + + ScriptInterpreterInstances::iterator pos, end = instances.end(); + ScriptInterpreterCreateInstance none_instance = nullptr; + for (pos = instances.begin(); pos != end; ++pos) + { + if (pos->language == lldb::eScriptLanguageNone) + none_instance = pos->create_callback; + + if (script_lang == pos->language) + return pos->create_callback(interpreter); + } + + // If we didn't find one, return the ScriptInterpreter for the null language. + assert(none_instance != nullptr); + return none_instance(interpreter); +} + #pragma mark SymbolFile struct SymbolFileInstance @@ -1771,13 +1983,15 @@ struct SymbolFileInstance SymbolFileInstance() : name(), description(), - create_callback(NULL) + create_callback(nullptr), + debugger_init_callback(nullptr) { } ConstString name; std::string description; SymbolFileCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector SymbolFileInstances; @@ -1802,7 +2016,8 @@ PluginManager::RegisterPlugin ( const ConstString &name, const char *description, - SymbolFileCreateInstance create_callback + SymbolFileCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback ) { if (create_callback) @@ -1813,6 +2028,7 @@ PluginManager::RegisterPlugin if (description && description[0]) instance.description = description; instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; Mutex::Locker locker (GetSymbolFileMutex ()); GetSymbolFileInstances ().push_back (instance); } @@ -2300,6 +2516,270 @@ PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const Const return NULL; } +#pragma mark TypeSystem + + +struct TypeSystemInstance +{ + TypeSystemInstance() : + name(), + description(), + create_callback(NULL) + { + } + + ConstString name; + std::string description; + TypeSystemCreateInstance create_callback; + TypeSystemEnumerateSupportedLanguages enumerate_callback; +}; + +typedef std::vector TypeSystemInstances; + +static Mutex & +GetTypeSystemMutex () +{ + static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static TypeSystemInstances & +GetTypeSystemInstances () +{ + static TypeSystemInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin (const ConstString &name, + const char *description, + TypeSystemCreateInstance create_callback, + TypeSystemEnumerateSupportedLanguages enumerate_supported_languages_callback) +{ + if (create_callback) + { + TypeSystemInstance instance; + assert ((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.enumerate_callback = enumerate_supported_languages_callback; + Mutex::Locker locker (GetTypeSystemMutex ()); + GetTypeSystemInstances ().push_back (instance); + } + return false; +} + +bool +PluginManager::UnregisterPlugin (TypeSystemCreateInstance create_callback) +{ + if (create_callback) + { + Mutex::Locker locker (GetTypeSystemMutex ()); + TypeSystemInstances &instances = GetTypeSystemInstances (); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (pos->create_callback == create_callback) + { + instances.erase(pos); + return true; + } + } + } + return false; +} + +TypeSystemCreateInstance +PluginManager::GetTypeSystemCreateCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetTypeSystemMutex ()); + TypeSystemInstances &instances = GetTypeSystemInstances (); + if (idx < instances.size()) + return instances[idx].create_callback; + return NULL; +} + +TypeSystemCreateInstance +PluginManager::GetTypeSystemCreateCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetTypeSystemMutex ()); + TypeSystemInstances &instances = GetTypeSystemInstances (); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->create_callback; + } + } + return NULL; +} + +TypeSystemEnumerateSupportedLanguages +PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetTypeSystemMutex ()); + TypeSystemInstances &instances = GetTypeSystemInstances (); + if (idx < instances.size()) + return instances[idx].enumerate_callback; + return NULL; +} + +TypeSystemEnumerateSupportedLanguages +PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetTypeSystemMutex ()); + TypeSystemInstances &instances = GetTypeSystemInstances (); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->enumerate_callback; + } + } + return NULL; +} + +#pragma mark REPL + +struct REPLInstance +{ + REPLInstance() : + name(), + description(), + create_callback(NULL) + { + } + + ConstString name; + std::string description; + REPLCreateInstance create_callback; + REPLEnumerateSupportedLanguages enumerate_languages_callback; +}; + +typedef std::vector REPLInstances; + +static Mutex & +GetREPLMutex () +{ + static Mutex g_instances_mutex (Mutex::eMutexTypeRecursive); + return g_instances_mutex; +} + +static REPLInstances & +GetREPLInstances () +{ + static REPLInstances g_instances; + return g_instances; +} + +bool +PluginManager::RegisterPlugin (const ConstString &name, + const char *description, + REPLCreateInstance create_callback, + REPLEnumerateSupportedLanguages enumerate_languages_callback) +{ + if (create_callback) + { + REPLInstance instance; + assert ((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.enumerate_languages_callback = enumerate_languages_callback; + Mutex::Locker locker (GetREPLMutex ()); + GetREPLInstances ().push_back (instance); + } + return false; +} + +bool +PluginManager::UnregisterPlugin (REPLCreateInstance create_callback) +{ + if (create_callback) + { + Mutex::Locker locker (GetREPLMutex ()); + REPLInstances &instances = GetREPLInstances (); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (pos->create_callback == create_callback) + { + instances.erase(pos); + return true; + } + } + } + return false; +} + +REPLCreateInstance +PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetREPLMutex ()); + REPLInstances &instances = GetREPLInstances (); + if (idx < instances.size()) + return instances[idx].create_callback; + return NULL; +} + +REPLCreateInstance +PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetREPLMutex ()); + REPLInstances &instances = GetREPLInstances (); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->create_callback; + } + } + return NULL; +} + +REPLEnumerateSupportedLanguages +PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetREPLMutex ()); + REPLInstances &instances = GetREPLInstances (); + if (idx < instances.size()) + return instances[idx].enumerate_languages_callback; + return NULL; +} + + +REPLEnumerateSupportedLanguages +PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) +{ + if (name) + { + Mutex::Locker locker (GetREPLMutex ()); + REPLInstances &instances = GetREPLInstances (); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++ pos) + { + if (name == pos->name) + return pos->enumerate_languages_callback; + } + } + return NULL; +} + #pragma mark PluginManager void @@ -2343,7 +2823,7 @@ PluginManager::DebuggerInitialize (Debugger &debugger) pos->debugger_init_callback (debugger); } } - + // Initialize the Process plugins { Mutex::Locker locker (GetProcessMutex()); @@ -2357,6 +2837,25 @@ PluginManager::DebuggerInitialize (Debugger &debugger) } } + // Initialize the SymbolFile plugins + { + Mutex::Locker locker (GetSymbolFileMutex()); + for (auto& sym_file: GetSymbolFileInstances()) + { + if (sym_file.debugger_init_callback) + sym_file.debugger_init_callback (debugger); + } + } + + // Initialize the OperatingSystem plugins + { + Mutex::Locker locker(GetOperatingSystemMutex()); + for (auto &os : GetOperatingSystemInstances()) + { + if (os.debugger_init_callback) + os.debugger_init_callback(debugger); + } + } } // This is the preferred new way to register plugin specific settings. e.g. @@ -2439,32 +2938,40 @@ GetDebuggerPropertyForPluginsOldStyle (Debugger &debugger, return lldb::OptionValuePropertiesSP(); } +namespace { + +typedef lldb::OptionValuePropertiesSP +GetDebuggerPropertyForPluginsPtr (Debugger&, const ConstString&, const ConstString&, bool can_create); lldb::OptionValuePropertiesSP -PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, const ConstString &setting_name) +GetSettingForPlugin (Debugger &debugger, + const ConstString &setting_name, + const ConstString &plugin_type_name, + GetDebuggerPropertyForPluginsPtr get_debugger_property= GetDebuggerPropertyForPlugins) { lldb::OptionValuePropertiesSP properties_sp; - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger, - ConstString("dynamic-loader"), - ConstString(), // not creating to so we don't need the description - false)); + lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property (debugger, + plugin_type_name, + ConstString(), // not creating to so we don't need the description + false)); if (plugin_type_properties_sp) - properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name); + properties_sp = plugin_type_properties_sp->GetSubProperty (nullptr, setting_name); return properties_sp; } bool -PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) +CreateSettingForPlugin (Debugger &debugger, + const ConstString &plugin_type_name, + const ConstString &plugin_type_desc, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property, + GetDebuggerPropertyForPluginsPtr get_debugger_property = GetDebuggerPropertyForPlugins) { if (properties_sp) { - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger, - ConstString("dynamic-loader"), - ConstString("Settings for dynamic loader plug-ins"), - true)); + lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property ( + debugger, plugin_type_name, plugin_type_desc, true)); if (plugin_type_properties_sp) { plugin_type_properties_sp->AppendProperty (properties_sp->GetName(), @@ -2477,56 +2984,65 @@ PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger, return false; } +const char* kDynamicLoaderPluginName("dynamic-loader"); +const char* kPlatformPluginName("platform"); +const char* kProcessPluginName("process"); +const char* kSymbolFilePluginName("symbol-file"); +const char* kJITLoaderPluginName("jit-loader"); + +} lldb::OptionValuePropertiesSP -PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name) +PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, + const ConstString &setting_name) { - lldb::OptionValuePropertiesSP properties_sp; - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger, - ConstString("platform"), - ConstString(), // not creating to so we don't need the description - false)); - if (plugin_type_properties_sp) - properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name); - return properties_sp; + return GetSettingForPlugin(debugger, setting_name, ConstString(kDynamicLoaderPluginName)); } bool -PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger, +PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, const ConstString &description, bool is_global_property) { - if (properties_sp) - { - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPluginsOldStyle (debugger, - ConstString("platform"), - ConstString("Settings for platform plug-ins"), - true)); - if (plugin_type_properties_sp) - { - plugin_type_properties_sp->AppendProperty (properties_sp->GetName(), - description, - is_global_property, - properties_sp); - return true; - } - } - return false; + return CreateSettingForPlugin(debugger, + ConstString(kDynamicLoaderPluginName), + ConstString("Settings for dynamic loader plug-ins"), + properties_sp, + description, + is_global_property); +} + + +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name) +{ + return GetSettingForPlugin(debugger, + setting_name, + ConstString(kPlatformPluginName), + GetDebuggerPropertyForPluginsOldStyle); +} + +bool +PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property) +{ + return CreateSettingForPlugin(debugger, + ConstString(kPlatformPluginName), + ConstString("Settings for platform plug-ins"), + properties_sp, + description, + is_global_property, + GetDebuggerPropertyForPluginsOldStyle); } lldb::OptionValuePropertiesSP PluginManager::GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name) { - lldb::OptionValuePropertiesSP properties_sp; - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger, - ConstString("process"), - ConstString(), // not creating to so we don't need the description - false)); - if (plugin_type_properties_sp) - properties_sp = plugin_type_properties_sp->GetSubProperty (NULL, setting_name); - return properties_sp; + return GetSettingForPlugin(debugger, setting_name, ConstString(kProcessPluginName)); } bool @@ -2534,22 +3050,88 @@ PluginManager::CreateSettingForProcessPlugin (Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, const ConstString &description, bool is_global_property) +{ + return CreateSettingForPlugin(debugger, + ConstString(kProcessPluginName), + ConstString("Settings for process plug-ins"), + properties_sp, + description, + is_global_property); +} + +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForSymbolFilePlugin (Debugger &debugger, + const ConstString &setting_name) +{ + return GetSettingForPlugin(debugger, setting_name, ConstString(kSymbolFilePluginName)); +} + +bool +PluginManager::CreateSettingForSymbolFilePlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property) +{ + return CreateSettingForPlugin(debugger, + ConstString(kSymbolFilePluginName), + ConstString("Settings for symbol file plug-ins"), + properties_sp, + description, + is_global_property); +} + +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForJITLoaderPlugin (Debugger &debugger, + const ConstString &setting_name) +{ + return GetSettingForPlugin(debugger, setting_name, ConstString(kJITLoaderPluginName)); +} + +bool +PluginManager::CreateSettingForJITLoaderPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property) +{ + return CreateSettingForPlugin(debugger, + ConstString(kJITLoaderPluginName), + ConstString("Settings for JIT loader plug-ins"), + properties_sp, + description, + is_global_property); +} + +static const char *kOperatingSystemPluginName("os"); + +lldb::OptionValuePropertiesSP +PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger, const ConstString &setting_name) +{ + lldb::OptionValuePropertiesSP properties_sp; + lldb::OptionValuePropertiesSP plugin_type_properties_sp( + GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), + ConstString(), // not creating to so we don't need the description + false)); + if (plugin_type_properties_sp) + properties_sp = plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); + return properties_sp; +} + +bool +PluginManager::CreateSettingForOperatingSystemPlugin(Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { if (properties_sp) { - lldb::OptionValuePropertiesSP plugin_type_properties_sp (GetDebuggerPropertyForPlugins (debugger, - ConstString("process"), - ConstString("Settings for process plug-ins"), - true)); + lldb::OptionValuePropertiesSP plugin_type_properties_sp( + GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), + ConstString("Settings for operating system plug-ins"), true)); if (plugin_type_properties_sp) { - plugin_type_properties_sp->AppendProperty (properties_sp->GetName(), - description, - is_global_property, - properties_sp); + plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), description, is_global_property, + properties_sp); return true; } } return false; } - diff --git a/source/Core/RegisterValue.cpp b/source/Core/RegisterValue.cpp index 272c1eecf920..d4ba9989c6a9 100644 --- a/source/Core/RegisterValue.cpp +++ b/source/Core/RegisterValue.cpp @@ -119,7 +119,7 @@ RegisterValue::GetAsMemoryData (const RegisterInfo *reg_info, return 0; } - // ReadRegister should have already been called on tgus object prior to + // ReadRegister should have already been called on this object prior to // calling this. if (GetType() == eTypeInvalid) { @@ -215,10 +215,10 @@ RegisterValue::SetFromMemoryData (const RegisterInfo *reg_info, } else if (value_type == eTypeBytes) { - m_data.buffer.byte_order = src_byte_order; + buffer.byte_order = src_byte_order; // Make sure to set the buffer length of the destination buffer to avoid - // problems due to uninitalized variables. - m_data.buffer.length = src_len; + // problems due to uninitialized variables. + buffer.length = src_len; } const uint32_t bytes_copied = src_data.CopyByteOrderedData (0, // src offset @@ -240,25 +240,23 @@ RegisterValue::GetScalarValue (Scalar &scalar) const case eTypeInvalid: break; case eTypeBytes: { - switch (m_data.buffer.length) + switch (buffer.length) { default: break; - case 1: scalar = m_data.uint8; return true; - case 2: scalar = m_data.uint16; return true; - case 4: scalar = m_data.uint32; return true; - case 8: scalar = m_data.uint64; return true; + case 1: scalar = *(const uint8_t *)buffer.bytes; return true; + case 2: scalar = *(const uint16_t *)buffer.bytes; return true; + case 4: scalar = *(const uint32_t *)buffer.bytes; return true; + case 8: scalar = *(const uint64_t *)buffer.bytes; return true; } } - case eTypeUInt8: scalar = m_data.uint8; return true; - case eTypeUInt16: scalar = m_data.uint16; return true; - case eTypeUInt32: scalar = m_data.uint32; return true; - case eTypeUInt64: scalar = m_data.uint64; return true; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: break; -#endif - case eTypeFloat: scalar = m_data.ieee_float; return true; - case eTypeDouble: scalar = m_data.ieee_double; return true; - case eTypeLongDouble: scalar = m_data.ieee_long_double; return true; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: scalar = m_scalar; return true; } return false; } @@ -289,10 +287,8 @@ RegisterValue::SetType (const RegisterInfo *reg_info) m_type = eTypeUInt32; else if (byte_size <= 8) m_type = eTypeUInt64; -#if defined (ENABLE_128_BIT_SUPPORT) else if (byte_size <= 16) m_type = eTypeUInt128; -#endif break; case eEncodingIEEE754: @@ -308,6 +304,7 @@ RegisterValue::SetType (const RegisterInfo *reg_info) m_type = eTypeBytes; break; } + m_scalar.SetType(reg_info); return m_type; } @@ -342,8 +339,9 @@ RegisterValue::SetValueFromData (const RegisterInfo *reg_info, DataExtractor &sr src_len = reg_info->byte_size; // Zero out the value in case we get partial data... - memset (m_data.buffer.bytes, 0, sizeof (m_data.buffer.bytes)); - + memset (buffer.bytes, 0, sizeof (buffer.bytes)); + + type128 int128; switch (SetType (reg_info)) { case eTypeInvalid: @@ -353,33 +351,38 @@ RegisterValue::SetValueFromData (const RegisterInfo *reg_info, DataExtractor &sr case eTypeUInt16: SetUInt16 (src.GetMaxU32 (&src_offset, src_len)); break; case eTypeUInt32: SetUInt32 (src.GetMaxU32 (&src_offset, src_len)); break; case eTypeUInt64: SetUInt64 (src.GetMaxU64 (&src_offset, src_len)); break; -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: { - __uint128_t data1 = src.GetU64 (&src_offset); - __uint128_t data2 = src.GetU64 (&src_offset); + uint64_t data1 = src.GetU64 (&src_offset); + uint64_t data2 = src.GetU64 (&src_offset); if (src.GetByteSize() == eByteOrderBig) - SetUInt128 (data1 << 64 + data2); + { + int128.x[0] = data1; + int128.x[1] = data2; + } else - SetUInt128 (data2 << 64 + data1); + { + int128.x[0] = data2; + int128.x[1] = data1; + } + SetUInt128 (llvm::APInt(128, 2, int128.x)); } break; -#endif case eTypeFloat: SetFloat (src.GetFloat (&src_offset)); break; case eTypeDouble: SetDouble(src.GetDouble (&src_offset)); break; case eTypeLongDouble: SetFloat (src.GetLongDouble (&src_offset)); break; case eTypeBytes: { - m_data.buffer.length = reg_info->byte_size; - m_data.buffer.byte_order = src.GetByteOrder(); - assert (m_data.buffer.length <= kMaxRegisterByteSize); - if (m_data.buffer.length > kMaxRegisterByteSize) - m_data.buffer.length = kMaxRegisterByteSize; + buffer.length = reg_info->byte_size; + buffer.byte_order = src.GetByteOrder(); + assert (buffer.length <= kMaxRegisterByteSize); + if (buffer.length > kMaxRegisterByteSize) + buffer.length = kMaxRegisterByteSize; if (src.CopyByteOrderedData (src_offset, // offset within "src" to start extracting data src_len, // src length - m_data.buffer.bytes, // dst buffer - m_data.buffer.length, // dst length - m_data.buffer.byte_order) == 0)// dst byte order + buffer.bytes, // dst buffer + buffer.length, // dst length + buffer.byte_order) == 0)// dst byte order { error.SetErrorString ("data copy failed data."); return error; @@ -459,6 +462,9 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va } bool success = false; const uint32_t byte_size = reg_info->byte_size; + static float flt_val; + static double dbl_val; + static long double ldbl_val; switch (reg_info->encoding) { case eEncodingInvalid: @@ -510,22 +516,31 @@ RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *va case eEncodingIEEE754: if (byte_size == sizeof (float)) { - if (::sscanf (value_str, "%f", &m_data.ieee_float) == 1) + if (::sscanf (value_str, "%f", &flt_val) == 1) + { + m_scalar = flt_val; m_type = eTypeFloat; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof (double)) { - if (::sscanf (value_str, "%lf", &m_data.ieee_double) == 1) + if (::sscanf (value_str, "%lf", &dbl_val) == 1) + { + m_scalar = dbl_val; m_type = eTypeDouble; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof (long double)) { - if (::sscanf (value_str, "%Lf", &m_data.ieee_long_double) == 1) + if (::sscanf (value_str, "%Lf", &ldbl_val) == 1) + { + m_scalar = ldbl_val; m_type = eTypeLongDouble; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } @@ -557,81 +572,11 @@ RegisterValue::SignExtend (uint32_t sign_bitpos) break; case eTypeUInt8: - if (sign_bitpos == (8-1)) - return true; - else if (sign_bitpos < (8-1)) - { - uint8_t sign_bit = 1u << sign_bitpos; - if (m_data.uint8 & sign_bit) - { - const uint8_t mask = ~(sign_bit) + 1u; - m_data.uint8 |= mask; - } - return true; - } - break; - case eTypeUInt16: - if (sign_bitpos == (16-1)) - return true; - else if (sign_bitpos < (16-1)) - { - uint16_t sign_bit = 1u << sign_bitpos; - if (m_data.uint16 & sign_bit) - { - const uint16_t mask = ~(sign_bit) + 1u; - m_data.uint16 |= mask; - } - return true; - } - break; - case eTypeUInt32: - if (sign_bitpos == (32-1)) - return true; - else if (sign_bitpos < (32-1)) - { - uint32_t sign_bit = 1u << sign_bitpos; - if (m_data.uint32 & sign_bit) - { - const uint32_t mask = ~(sign_bit) + 1u; - m_data.uint32 |= mask; - } - return true; - } - break; - case eTypeUInt64: - if (sign_bitpos == (64-1)) - return true; - else if (sign_bitpos < (64-1)) - { - uint64_t sign_bit = 1ull << sign_bitpos; - if (m_data.uint64 & sign_bit) - { - const uint64_t mask = ~(sign_bit) + 1ull; - m_data.uint64 |= mask; - } - return true; - } - break; - -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (sign_bitpos == (128-1)) - return true; - else if (sign_bitpos < (128-1)) - { - __uint128_t sign_bit = (__uint128_t)1u << sign_bitpos; - if (m_data.uint128 & sign_bit) - { - const uint128_t mask = ~(sign_bit) + 1u; - m_data.uint128 |= mask; - } - return true; - } - break; -#endif + return m_scalar.SignExtend(sign_bitpos); case eTypeFloat: case eTypeDouble: case eTypeLongDouble: @@ -649,21 +594,19 @@ RegisterValue::CopyValue (const RegisterValue &rhs) { case eTypeInvalid: return false; - case eTypeUInt8: m_data.uint8 = rhs.m_data.uint8; break; - case eTypeUInt16: m_data.uint16 = rhs.m_data.uint16; break; - case eTypeUInt32: m_data.uint32 = rhs.m_data.uint32; break; - case eTypeUInt64: m_data.uint64 = rhs.m_data.uint64; break; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: m_data.uint128 = rhs.m_data.uint128; break; -#endif - case eTypeFloat: m_data.ieee_float = rhs.m_data.ieee_float; break; - case eTypeDouble: m_data.ieee_double = rhs.m_data.ieee_double; break; - case eTypeLongDouble: m_data.ieee_long_double = rhs.m_data.ieee_long_double; break; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: m_scalar = rhs.m_scalar; break; case eTypeBytes: - assert (rhs.m_data.buffer.length <= kMaxRegisterByteSize); - ::memcpy (m_data.buffer.bytes, rhs.m_data.buffer.bytes, kMaxRegisterByteSize); - m_data.buffer.length = rhs.m_data.buffer.length; - m_data.buffer.byte_order = rhs.m_data.buffer.byte_order; + assert (rhs.buffer.length <= kMaxRegisterByteSize); + ::memcpy (buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); + buffer.length = rhs.buffer.length; + buffer.byte_order = rhs.buffer.byte_order; break; } return true; @@ -678,15 +621,15 @@ RegisterValue::GetAsUInt16 (uint16_t fail_value, bool *success_ptr) const switch (m_type) { default: break; - case eTypeUInt8: return m_data.uint8; - case eTypeUInt16: return m_data.uint16; + case eTypeUInt8: + case eTypeUInt16: return m_scalar.UShort(fail_value); case eTypeBytes: { - switch (m_data.buffer.length) + switch (buffer.length) { default: break; - case 1: return m_data.uint8; - case 2: return m_data.uint16; + case 1: + case 2: return *(const uint16_t *)buffer.bytes; } } break; @@ -704,29 +647,20 @@ RegisterValue::GetAsUInt32 (uint32_t fail_value, bool *success_ptr) const switch (m_type) { default: break; - case eTypeUInt8: return m_data.uint8; - case eTypeUInt16: return m_data.uint16; - case eTypeUInt32: return m_data.uint32; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: case eTypeFloat: - if (sizeof(float) == sizeof(uint32_t)) - return m_data.uint32; - break; case eTypeDouble: - if (sizeof(double) == sizeof(uint32_t)) - return m_data.uint32; - break; - case eTypeLongDouble: - if (sizeof(long double) == sizeof(uint32_t)) - return m_data.uint32; - break; + case eTypeLongDouble: return m_scalar.UInt(fail_value); case eTypeBytes: { - switch (m_data.buffer.length) + switch (buffer.length) { default: break; - case 1: return m_data.uint8; - case 2: return m_data.uint16; - case 4: return m_data.uint32; + case 1: + case 2: + case 4: return *(const uint32_t *)buffer.bytes; } } break; @@ -744,31 +678,22 @@ RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const switch (m_type) { default: break; - case eTypeUInt8: return m_data.uint8; - case eTypeUInt16: return m_data.uint16; - case eTypeUInt32: return m_data.uint32; - case eTypeUInt64: return m_data.uint64; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: case eTypeFloat: - if (sizeof(float) == sizeof(uint64_t)) - return m_data.uint64; - break; case eTypeDouble: - if (sizeof(double) == sizeof(uint64_t)) - return m_data.uint64; - break; - case eTypeLongDouble: - if (sizeof(long double) == sizeof(uint64_t)) - return m_data.uint64; - break; + case eTypeLongDouble: return m_scalar.ULongLong(fail_value); case eTypeBytes: { - switch (m_data.buffer.length) + switch (buffer.length) { default: break; - case 1: return m_data.uint8; - case 2: return m_data.uint16; - case 4: return m_data.uint32; - case 8: return m_data.uint64; + case 1: + case 2: + case 4: + case 8: return *(const uint64_t *)buffer.bytes; } } break; @@ -778,43 +703,36 @@ RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const return fail_value; } -#if defined (ENABLE_128_BIT_SUPPORT) -__uint128_t -RegisterValue::GetAsUInt128 (__uint128_t fail_value, bool *success_ptr) const +llvm::APInt +RegisterValue::GetAsUInt128 (const llvm::APInt& fail_value, bool *success_ptr) const { if (success_ptr) *success_ptr = true; switch (m_type) { default: break; - case eTypeUInt8: return m_data.uint8; - case eTypeUInt16: return m_data.uint16; - case eTypeUInt32: return m_data.uint32; - case eTypeUInt64: return m_data.uint64; - case eTypeUInt128: return m_data.uint128; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: case eTypeFloat: - if (sizeof(float) == sizeof(__uint128_t)) - return m_data.uint128; - break; case eTypeDouble: - if (sizeof(double) == sizeof(__uint128_t)) - return m_data.uint128; - break; - case eTypeLongDouble: - if (sizeof(long double) == sizeof(__uint128_t)) - return m_data.uint128; - break; + case eTypeLongDouble: return m_scalar.UInt128(fail_value); case eTypeBytes: { - switch (m_data.buffer.length) + switch (buffer.length) { - default: - break; - case 1: return m_data.uint8; - case 2: return m_data.uint16; - case 4: return m_data.uint32; - case 8: return m_data.uint64; - case 16: return m_data.uint128; + default: + break; + case 1: + case 2: + case 4: + case 8: + case 16: + { + return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)buffer.bytes)->x); + } } } break; @@ -823,7 +741,7 @@ RegisterValue::GetAsUInt128 (__uint128_t fail_value, bool *success_ptr) const *success_ptr = false; return fail_value; } -#endif + float RegisterValue::GetAsFloat (float fail_value, bool *success_ptr) const { @@ -833,28 +751,12 @@ RegisterValue::GetAsFloat (float fail_value, bool *success_ptr) const { default: break; case eTypeUInt32: - if (sizeof(float) == sizeof(m_data.uint32)) - return m_data.ieee_float; - break; case eTypeUInt64: - if (sizeof(float) == sizeof(m_data.uint64)) - return m_data.ieee_float; - break; -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (sizeof(float) == sizeof(m_data.uint128)) - return m_data.ieee_float; - break; -#endif - case eTypeFloat: return m_data.ieee_float; + case eTypeFloat: case eTypeDouble: - if (sizeof(float) == sizeof(double)) - return m_data.ieee_float; - break; case eTypeLongDouble: - if (sizeof(float) == sizeof(long double)) - return m_data.ieee_float; - break; + return m_scalar.Float(fail_value); } if (success_ptr) *success_ptr = false; @@ -872,27 +774,12 @@ RegisterValue::GetAsDouble (double fail_value, bool *success_ptr) const break; case eTypeUInt32: - if (sizeof(double) == sizeof(m_data.uint32)) - return m_data.ieee_double; - break; - case eTypeUInt64: - if (sizeof(double) == sizeof(m_data.uint64)) - return m_data.ieee_double; - break; - -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (sizeof(double) == sizeof(m_data.uint128)) - return m_data.ieee_double; -#endif - case eTypeFloat: return m_data.ieee_float; - case eTypeDouble: return m_data.ieee_double; - + case eTypeFloat: + case eTypeDouble: case eTypeLongDouble: - if (sizeof(double) == sizeof(long double)) - return m_data.ieee_double; - break; + return m_scalar.Double(fail_value); } if (success_ptr) *success_ptr = false; @@ -910,24 +797,12 @@ RegisterValue::GetAsLongDouble (long double fail_value, bool *success_ptr) const break; case eTypeUInt32: - if (sizeof(long double) == sizeof(m_data.uint32)) - return m_data.ieee_long_double; - break; - case eTypeUInt64: - if (sizeof(long double) == sizeof(m_data.uint64)) - return m_data.ieee_long_double; - break; - -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (sizeof(long double) == sizeof(m_data.uint128)) - return m_data.ieee_long_double; -#endif - case eTypeFloat: return m_data.ieee_float; - case eTypeDouble: return m_data.ieee_double; - case eTypeLongDouble: return m_data.ieee_long_double; - break; + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.LongDouble(); } if (success_ptr) *success_ptr = false; @@ -940,17 +815,15 @@ RegisterValue::GetBytes () const switch (m_type) { case eTypeInvalid: break; - case eTypeUInt8: return &m_data.uint8; - case eTypeUInt16: return &m_data.uint16; - case eTypeUInt32: return &m_data.uint32; - case eTypeUInt64: return &m_data.uint64; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: return &m_data.uint128; -#endif - case eTypeFloat: return &m_data.ieee_float; - case eTypeDouble: return &m_data.ieee_double; - case eTypeLongDouble: return &m_data.ieee_long_double; - case eTypeBytes: return m_data.buffer.bytes; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: return m_scalar.GetBytes(); + case eTypeBytes: return buffer.bytes; } return NULL; } @@ -961,17 +834,15 @@ RegisterValue::GetBytes () switch (m_type) { case eTypeInvalid: break; - case eTypeUInt8: return &m_data.uint8; - case eTypeUInt16: return &m_data.uint16; - case eTypeUInt32: return &m_data.uint32; - case eTypeUInt64: return &m_data.uint64; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: return &m_data.uint128; -#endif - case eTypeFloat: return &m_data.ieee_float; - case eTypeDouble: return &m_data.ieee_double; - case eTypeLongDouble: return &m_data.ieee_long_double; - case eTypeBytes: return m_data.buffer.bytes; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: return m_scalar.GetBytes(); + case eTypeBytes: return buffer.bytes; } return NULL; } @@ -982,17 +853,15 @@ RegisterValue::GetByteSize () const switch (m_type) { case eTypeInvalid: break; - case eTypeUInt8: return sizeof(m_data.uint8); - case eTypeUInt16: return sizeof(m_data.uint16); - case eTypeUInt32: return sizeof(m_data.uint32); - case eTypeUInt64: return sizeof(m_data.uint64); -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: return sizeof(m_data.uint128); -#endif - case eTypeFloat: return sizeof(m_data.ieee_float); - case eTypeDouble: return sizeof(m_data.ieee_double); - case eTypeLongDouble: return sizeof(m_data.ieee_long_double); - case eTypeBytes: return m_data.buffer.length; + case eTypeUInt8: return 1; + case eTypeUInt16: return 2; + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: return m_scalar.GetByteSize(); + case eTypeBytes: return buffer.length; } return 0; } @@ -1021,12 +890,10 @@ RegisterValue::SetUInt (uint64_t uint, uint32_t byte_size) { SetUInt64 (uint); } -#if defined (ENABLE_128_BIT_SUPPORT) else if (byte_size <= 16) { - SetUInt128 (uint); + SetUInt128 (llvm::APInt(128, uint)); } -#endif else return false; return true; @@ -1036,21 +903,21 @@ void RegisterValue::SetBytes (const void *bytes, size_t length, lldb::ByteOrder byte_order) { // If this assertion fires off we need to increase the size of - // m_data.buffer.bytes, or make it something that is allocated on + // buffer.bytes, or make it something that is allocated on // the heap. Since the data buffer is in a union, we can't make it // a collection class like SmallVector... if (bytes && length > 0) { - assert (length <= sizeof (m_data.buffer.bytes) && "Storing too many bytes in a RegisterValue."); + assert (length <= sizeof (buffer.bytes) && "Storing too many bytes in a RegisterValue."); m_type = eTypeBytes; - m_data.buffer.length = length; - memcpy (m_data.buffer.bytes, bytes, length); - m_data.buffer.byte_order = byte_order; + buffer.length = length; + memcpy (buffer.bytes, bytes, length); + buffer.byte_order = byte_order; } else { m_type = eTypeInvalid; - m_data.buffer.length = 0; + buffer.length = 0; } } @@ -1063,25 +930,23 @@ RegisterValue::operator == (const RegisterValue &rhs) const switch (m_type) { case eTypeInvalid: return true; - case eTypeUInt8: return m_data.uint8 == rhs.m_data.uint8; - case eTypeUInt16: return m_data.uint16 == rhs.m_data.uint16; - case eTypeUInt32: return m_data.uint32 == rhs.m_data.uint32; - case eTypeUInt64: return m_data.uint64 == rhs.m_data.uint64; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: return m_data.uint128 == rhs.m_data.uint128; -#endif - case eTypeFloat: return m_data.ieee_float == rhs.m_data.ieee_float; - case eTypeDouble: return m_data.ieee_double == rhs.m_data.ieee_double; - case eTypeLongDouble: return m_data.ieee_long_double == rhs.m_data.ieee_long_double; + 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 (m_data.buffer.length != rhs.m_data.buffer.length) + if (buffer.length != rhs.buffer.length) return false; else { - uint8_t length = m_data.buffer.length; + uint8_t length = buffer.length; if (length > kMaxRegisterByteSize) length = kMaxRegisterByteSize; - return memcmp (m_data.buffer.bytes, rhs.m_data.buffer.bytes, length) == 0; + return memcmp (buffer.bytes, rhs.buffer.bytes, length) == 0; } break; } @@ -1097,27 +962,25 @@ RegisterValue::operator != (const RegisterValue &rhs) const switch (m_type) { case eTypeInvalid: return false; - case eTypeUInt8: return m_data.uint8 != rhs.m_data.uint8; - case eTypeUInt16: return m_data.uint16 != rhs.m_data.uint16; - case eTypeUInt32: return m_data.uint32 != rhs.m_data.uint32; - case eTypeUInt64: return m_data.uint64 != rhs.m_data.uint64; -#if defined (ENABLE_128_BIT_SUPPORT) - case eTypeUInt128: return m_data.uint128 != rhs.m_data.uint128; -#endif - case eTypeFloat: return m_data.ieee_float != rhs.m_data.ieee_float; - case eTypeDouble: return m_data.ieee_double != rhs.m_data.ieee_double; - case eTypeLongDouble: return m_data.ieee_long_double != rhs.m_data.ieee_long_double; + 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 (m_data.buffer.length != rhs.m_data.buffer.length) + if (buffer.length != rhs.buffer.length) { return true; } else { - uint8_t length = m_data.buffer.length; + uint8_t length = buffer.length; if (length > kMaxRegisterByteSize) length = kMaxRegisterByteSize; - return memcmp (m_data.buffer.bytes, rhs.m_data.buffer.bytes, length) != 0; + return memcmp (buffer.bytes, rhs.buffer.bytes, length) != 0; } break; } @@ -1132,63 +995,35 @@ RegisterValue::ClearBit (uint32_t bit) case eTypeInvalid: break; - case eTypeUInt8: - if (bit < 8) - { - m_data.uint8 &= ~(1u << bit); - return true; - } - break; - + case eTypeUInt8: case eTypeUInt16: - if (bit < 16) - { - m_data.uint16 &= ~(1u << bit); - return true; - } - break; - case eTypeUInt32: - if (bit < 32) - { - m_data.uint32 &= ~(1u << bit); - return true; - } - break; - case eTypeUInt64: - if (bit < 64) - { - m_data.uint64 &= ~(1ull << (uint64_t)bit); - return true; - } - break; -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (bit < 64) + if (bit < (GetByteSize() * 8)) { - m_data.uint128 &= ~((__uint128_t)1ull << (__uint128_t)bit); - return true; + return m_scalar.ClearBit(bit); } -#endif + break; + case eTypeFloat: case eTypeDouble: case eTypeLongDouble: break; case eTypeBytes: - if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle) + if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle) { uint32_t byte_idx; - if (m_data.buffer.byte_order == eByteOrderBig) - byte_idx = m_data.buffer.length - (bit / 8) - 1; + if (buffer.byte_order == eByteOrderBig) + byte_idx = buffer.length - (bit / 8) - 1; else byte_idx = bit / 8; const uint32_t byte_bit = bit % 8; - if (byte_idx < m_data.buffer.length) + if (byte_idx < buffer.length) { - m_data.buffer.bytes[byte_idx] &= ~(1u << byte_bit); + buffer.bytes[byte_idx] &= ~(1u << byte_bit); return true; } } @@ -1207,62 +1042,34 @@ RegisterValue::SetBit (uint32_t bit) break; case eTypeUInt8: - if (bit < 8) - { - m_data.uint8 |= (1u << bit); - return true; - } - break; - case eTypeUInt16: - if (bit < 16) - { - m_data.uint16 |= (1u << bit); - return true; - } - break; - case eTypeUInt32: - if (bit < 32) - { - m_data.uint32 |= (1u << bit); - return true; - } - break; - case eTypeUInt64: - if (bit < 64) - { - m_data.uint64 |= (1ull << (uint64_t)bit); - return true; - } - break; -#if defined (ENABLE_128_BIT_SUPPORT) case eTypeUInt128: - if (bit < 64) + if (bit < (GetByteSize() * 8)) { - m_data.uint128 |= ((__uint128_t)1ull << (__uint128_t)bit); - return true; + return m_scalar.SetBit(bit); } -#endif + break; + case eTypeFloat: case eTypeDouble: case eTypeLongDouble: break; case eTypeBytes: - if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle) + if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle) { uint32_t byte_idx; - if (m_data.buffer.byte_order == eByteOrderBig) - byte_idx = m_data.buffer.length - (bit / 8) - 1; + if (buffer.byte_order == eByteOrderBig) + byte_idx = buffer.length - (bit / 8) - 1; else byte_idx = bit / 8; const uint32_t byte_bit = bit % 8; - if (byte_idx < m_data.buffer.length) + if (byte_idx < buffer.length) { - m_data.buffer.bytes[byte_idx] |= (1u << byte_bit); + buffer.bytes[byte_idx] |= (1u << byte_bit); return true; } } diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp index 3f712e1b2daa..767521500af8 100644 --- a/source/Core/RegularExpression.cpp +++ b/source/Core/RegularExpression.cpp @@ -153,7 +153,7 @@ RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::str llvm::StringRef match_str_ref; if (GetMatchAtIndex(s, idx, match_str_ref)) { - match_str = std::move(match_str_ref.str()); + match_str = match_str_ref.str(); return true; } return false; @@ -258,4 +258,3 @@ RegularExpression::operator < (const RegularExpression& rhs) const { return (m_re < rhs.m_re); } - diff --git a/source/Core/Scalar.cpp b/source/Core/Scalar.cpp index 0022c348bfee..586969b2d50a 100644 --- a/source/Core/Scalar.cpp +++ b/source/Core/Scalar.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "lldb/Interpreter/Args.h" #include "lldb/Core/Error.h" @@ -77,7 +78,7 @@ PromoteToMaxType //---------------------------------------------------------------------- Scalar::Scalar() : m_type(e_void), - m_data() + m_float((float)0) { } @@ -86,7 +87,8 @@ Scalar::Scalar() : //---------------------------------------------------------------------- Scalar::Scalar(const Scalar& rhs) : m_type(rhs.m_type), - m_data(rhs.m_data) // TODO: verify that for C++ this will correctly copy the union?? + m_integer(rhs.m_integer), + m_float(rhs.m_float) { } @@ -135,29 +137,109 @@ bool Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const { size_t byte_size = GetByteSize(); + static float f_val; + static double d_val; if (byte_size > 0) { if (limit_byte_size < byte_size) { - if (lldb::endian::InlHostByteOrder() == eByteOrderLittle) + if (endian::InlHostByteOrder() == eByteOrderLittle) { // On little endian systems if we want fewer bytes from the // current type we just specify fewer bytes since the LSByte // is first... - data.SetData((uint8_t*)&m_data, limit_byte_size, lldb::endian::InlHostByteOrder()); + switch(m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + data.SetData((const uint8_t *)m_integer.getRawData(), limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_float: + f_val = m_float.convertToFloat(); + data.SetData((uint8_t *)&f_val, limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_double: + d_val = m_float.convertToDouble(); + data.SetData((uint8_t *)&d_val, limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_long_double: + static llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + data.SetData((const uint8_t *)ldbl_val.getRawData(), limit_byte_size, endian::InlHostByteOrder()); + return true; + } } - else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) + else if (endian::InlHostByteOrder() == eByteOrderBig) { // On big endian systems if we want fewer bytes from the // current type have to advance our initial byte pointer and // trim down the number of bytes since the MSByte is first - data.SetData(((uint8_t*)&m_data) + byte_size - limit_byte_size, limit_byte_size, lldb::endian::InlHostByteOrder()); + switch(m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + data.SetData((const uint8_t *)m_integer.getRawData() + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_float: + f_val = m_float.convertToFloat(); + data.SetData((uint8_t *)&f_val + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_double: + d_val = m_float.convertToDouble(); + data.SetData((uint8_t *)&d_val + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder()); + return true; + case e_long_double: + static llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + data.SetData((const uint8_t *)ldbl_val.getRawData() + byte_size - limit_byte_size, limit_byte_size, endian::InlHostByteOrder()); + return true; + } } } else { // We want all of the data - data.SetData((uint8_t*)&m_data, byte_size, lldb::endian::InlHostByteOrder()); + switch(m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + data.SetData((const uint8_t *)m_integer.getRawData(), byte_size, endian::InlHostByteOrder()); + return true; + case e_float: + f_val = m_float.convertToFloat(); + data.SetData((uint8_t *)&f_val, byte_size, endian::InlHostByteOrder()); + return true; + case e_double: + d_val = m_float.convertToDouble(); + data.SetData((uint8_t *)&d_val, byte_size, endian::InlHostByteOrder()); + return true; + case e_long_double: + static llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + data.SetData((const uint8_t *)ldbl_val.getRawData(), byte_size, endian::InlHostByteOrder()); + return true; + } } return true; } @@ -165,6 +247,37 @@ Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const return false; } +void * +Scalar::GetBytes() const +{ + static float_t flt_val; + static double_t dbl_val; + switch (m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return const_cast(reinterpret_cast(m_integer.getRawData())); + case e_float: + flt_val = m_float.convertToFloat(); + return (void *)&flt_val; + case e_double: + dbl_val = m_float.convertToDouble(); + return (void *)&dbl_val; + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return const_cast(reinterpret_cast(ldbl_val.getRawData())); + } + return NULL; +} + size_t Scalar::GetByteSize() const { @@ -172,15 +285,17 @@ Scalar::GetByteSize() const { case e_void: break; - case e_sint: return sizeof(m_data.sint); - case e_uint: return sizeof(m_data.uint); - case e_slong: return sizeof(m_data.slong); - case e_ulong: return sizeof(m_data.ulong); - case e_slonglong: return sizeof(m_data.slonglong); - case e_ulonglong: return sizeof(m_data.ulonglong); - case e_float: return sizeof(m_data.flt); - case e_double: return sizeof(m_data.dbl); - case e_long_double: return sizeof(m_data.ldbl); + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: return (m_integer.getBitWidth() / 8); + case e_float: return sizeof(float_t); + case e_double: return sizeof(double_t); + case e_long_double: return sizeof(long_double_t); } return 0; } @@ -188,19 +303,24 @@ Scalar::GetByteSize() const bool Scalar::IsZero() const { + llvm::APInt zero_int = llvm::APInt::getNullValue(m_integer.getBitWidth() / 8); switch (m_type) { case e_void: break; - case e_sint: return m_data.sint == 0; - case e_uint: return m_data.uint == 0; - case e_slong: return m_data.slong == 0; - case e_ulong: return m_data.ulong == 0; - case e_slonglong: return m_data.slonglong == 0; - case e_ulonglong: return m_data.ulonglong == 0; - case e_float: return m_data.flt == 0.0f; - case e_double: return m_data.dbl == 0.0; - case e_long_double: return m_data.ldbl == 0.0; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return llvm::APInt::isSameValue(zero_int, m_integer); + case e_float: + case e_double: + case e_long_double: + return m_float.isZero(); } return false; } @@ -208,6 +328,7 @@ Scalar::IsZero() const void Scalar::GetValue (Stream *s, bool show_type) const { + const uint64_t *src; if (show_type) s->Printf("(%s) ", GetTypeAsCString()); @@ -215,15 +336,26 @@ Scalar::GetValue (Stream *s, bool show_type) const { case e_void: break; - case e_sint: s->Printf("%i", m_data.sint); break; - case e_uint: s->Printf("0x%8.8x", m_data.uint); break; - case e_slong: s->Printf("%li", m_data.slong); break; - case e_ulong: s->Printf("0x%8.8lx", m_data.ulong); break; - case e_slonglong: s->Printf("%lli", m_data.slonglong); break; - case e_ulonglong: s->Printf("0x%16.16llx", m_data.ulonglong); break; - case e_float: s->Printf("%f", m_data.flt); break; - case e_double: s->Printf("%g", m_data.dbl); break; - case e_long_double: s->Printf("%Lg", m_data.ldbl); break; + case e_sint: s->Printf("%i", *(const sint_t *) m_integer.getRawData()); break; + case e_uint: s->Printf("0x%8.8x", *(const uint_t *) m_integer.getRawData()); break; + case e_slong: s->Printf("%li", *(const slong_t *) m_integer.getRawData()); break; + case e_ulong: s->Printf("0x%8.8lx", *(const ulong_t *) m_integer.getRawData()); break; + case e_slonglong: s->Printf("%lli", *(const slonglong_t *) m_integer.getRawData()); break; + case e_ulonglong: s->Printf("0x%16.16llx", *(const ulonglong_t *) m_integer.getRawData()); break; + case e_sint128: + src = m_integer.getRawData(); + s->Printf("%lli%lli", *(const slonglong_t *)src, *(const slonglong_t *)(src + 1)); + break; + case e_uint128: + src = m_integer.getRawData(); + s->Printf("0x%16.16llx%16.16llx", *(const ulonglong_t *)src, *(const ulonglong_t *)(src + 1)); + break; + case e_float: s->Printf("%f", m_float.convertToFloat()); break; + case e_double: s->Printf("%g", m_float.convertToDouble()); break; + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + s->Printf("%Lg", *(const long_double_t *)ldbl_val.getRawData()); + break; } } @@ -239,6 +371,8 @@ Scalar::GetTypeAsCString() const case e_ulong: return "unsigned long"; case e_slonglong: return "long long"; case e_ulonglong: return "unsigned long long"; + case e_sint128: return "int128_t"; + case e_uint128: return "unsigned int128_t"; case e_float: return "float"; case e_double: return "double"; case e_long_double: return "long double"; @@ -257,7 +391,8 @@ Scalar::operator=(const Scalar& rhs) if (this != &rhs) { m_type = rhs.m_type; - ::memcpy (&m_data, &rhs.m_data, sizeof(m_data)); + m_integer = llvm::APInt(rhs.m_integer); + m_float = rhs.m_float; } return *this; } @@ -266,7 +401,7 @@ Scalar& Scalar::operator= (const int v) { m_type = e_sint; - m_data.sint = v; + m_integer = llvm::APInt(sizeof(int) * 8, v, true); return *this; } @@ -275,7 +410,7 @@ Scalar& Scalar::operator= (unsigned int v) { m_type = e_uint; - m_data.uint = v; + m_integer = llvm::APInt(sizeof(int) * 8, v); return *this; } @@ -283,7 +418,7 @@ Scalar& Scalar::operator= (long v) { m_type = e_slong; - m_data.slong = v; + m_integer = llvm::APInt(sizeof(long) * 8, v, true); return *this; } @@ -291,7 +426,7 @@ Scalar& Scalar::operator= (unsigned long v) { m_type = e_ulong; - m_data.ulong = v; + m_integer = llvm::APInt(sizeof(long) * 8, v); return *this; } @@ -299,7 +434,7 @@ Scalar& Scalar::operator= (long long v) { m_type = e_slonglong; - m_data.slonglong = v; + m_integer = llvm::APInt(sizeof(long) * 8, v, true); return *this; } @@ -307,7 +442,7 @@ Scalar& Scalar::operator= (unsigned long long v) { m_type = e_ulonglong; - m_data.ulonglong = v; + m_integer = llvm::APInt(sizeof(long long) * 8, v); return *this; } @@ -315,7 +450,7 @@ Scalar& Scalar::operator= (float v) { m_type = e_float; - m_data.flt = v; + m_float = llvm::APFloat(v); return *this; } @@ -323,7 +458,7 @@ Scalar& Scalar::operator= (double v) { m_type = e_double; - m_data.dbl = v; + m_float = llvm::APFloat(v); return *this; } @@ -331,7 +466,40 @@ Scalar& Scalar::operator= (long double v) { m_type = e_long_double; - m_data.ldbl = v; + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + return *this; +} + +Scalar& +Scalar::operator= (llvm::APInt rhs) +{ + m_integer = llvm::APInt(rhs); + switch(m_integer.getBitWidth()) + { + case 8: + case 16: + case 32: + if(m_integer.isSignedIntN(sizeof(sint_t) * 8)) + m_type = e_sint; + else + m_type = e_uint; + break; + case 64: + if(m_integer.isSignedIntN(sizeof(slonglong_t) * 8)) + m_type = e_slonglong; + else + m_type = e_ulonglong; + break; + case 128: + if(m_integer.isSignedIntN(BITWIDTH_INT128)) + m_type = e_sint128; + else + m_type = e_uint128; + break; + } return *this; } @@ -354,128 +522,455 @@ Scalar::Promote(Scalar::Type type) case e_sint: switch (type) { - case e_void: break; - case e_sint: success = true; break; - case e_uint: m_data.uint = m_data.sint; success = true; break; - case e_slong: m_data.slong = m_data.sint; success = true; break; - case e_ulong: m_data.ulong = m_data.sint; success = true; break; - case e_slonglong: m_data.slonglong = m_data.sint; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.sint; success = true; break; - case e_float: m_data.flt = m_data.sint; success = true; break; - case e_double: m_data.dbl = m_data.sint; success = true; break; - case e_long_double: m_data.ldbl = m_data.sint; success = true; break; + case e_void: break; + case e_sint: success = true; break; + case e_uint: + { + m_integer = llvm::APInt(sizeof(uint_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_slong: + { + m_integer = llvm::APInt(sizeof(slong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulong: + { + m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_slonglong: + { + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulonglong: + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_uint: switch (type) { - case e_void: - case e_sint: break; - case e_uint: success = true; break; - case e_slong: m_data.slong = m_data.uint; success = true; break; - case e_ulong: m_data.ulong = m_data.uint; success = true; break; - case e_slonglong: m_data.slonglong = m_data.uint; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.uint; success = true; break; - case e_float: m_data.flt = m_data.uint; success = true; break; - case e_double: m_data.dbl = m_data.uint; success = true; break; - case e_long_double: m_data.ldbl = m_data.uint; success = true; break; + case e_void: + case e_sint: break; + case e_uint: success = true; break; + case e_slong: + { + m_integer = llvm::APInt(sizeof(slong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulong: + { + m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_slonglong: + { + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulonglong: + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_slong: switch (type) { - case e_void: - case e_sint: - case e_uint: break; - case e_slong: success = true; break; - case e_ulong: m_data.ulong = m_data.slong; success = true; break; - case e_slonglong: m_data.slonglong = m_data.slong; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.slong; success = true; break; - case e_float: m_data.flt = m_data.slong; success = true; break; - case e_double: m_data.dbl = m_data.slong; success = true; break; - case e_long_double: m_data.ldbl = m_data.slong; success = true; break; + case e_void: + case e_sint: + case e_uint: break; + case e_slong: success = true; break; + case e_ulong: + { + m_integer = llvm::APInt(sizeof(ulong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_slonglong: + { + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulonglong: + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_ulong: switch (type) { - case e_void: - case e_sint: - case e_uint: - case e_slong: break; - case e_ulong: success = true; break; - case e_slonglong: m_data.slonglong = m_data.ulong; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.ulong; success = true; break; - case e_float: m_data.flt = m_data.ulong; success = true; break; - case e_double: m_data.dbl = m_data.ulong; success = true; break; - case e_long_double: m_data.ldbl = m_data.ulong; success = true; break; + case e_void: + case e_sint: + case e_uint: + case e_slong: break; + case e_ulong: success = true; break; + case e_slonglong: + { + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + success = true; + break; + } + case e_ulonglong: + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_slonglong: switch (type) { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: break; - case e_slonglong: success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.slonglong; success = true; break; - case e_float: m_data.flt = m_data.slonglong; success = true; break; - case e_double: m_data.dbl = m_data.slonglong; success = true; break; - case e_long_double: m_data.ldbl = m_data.slonglong; success = true; break; + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: break; + case e_slonglong: success = true; break; + case e_ulonglong: + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + success = true; + break; + } + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_ulonglong: switch (type) { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: break; - case e_ulonglong: success = true; break; - case e_float: m_data.flt = m_data.ulonglong; success = true; break; - case e_double: m_data.dbl = m_data.ulonglong; success = true; break; - case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break; + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: break; + case e_ulonglong: success = true; break; + case e_sint128: + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } + } + break; + + case e_sint128: + switch (type) + { + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: break; + case e_sint128: success = true; break; + case e_uint128: + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } + } + break; + + case e_uint128: + switch (type) + { + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: break; + case e_uint128: success = true; break; + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; case e_float: switch (type) { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: break; - case e_float: success = true; break; - case e_double: m_data.dbl = m_data.flt; success = true; break; - case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break; + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: break; + case e_float: success = true; break; + case e_double: + { + m_float = llvm::APFloat((float_t)m_float.convertToFloat()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); + success = true; + break; + } } break; case e_double: switch (type) { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_float: break; - case e_double: success = true; break; - case e_long_double: m_data.ldbl = m_data.dbl; success = true; break; + case e_void: + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_float: break; + case e_double: success = true; break; + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); + success = true; + break; + } } break; @@ -489,6 +984,8 @@ Scalar::Promote(Scalar::Type type) case e_ulong: case e_slonglong: case e_ulonglong: + case e_sint128: + case e_uint128: case e_float: case e_double: break; case e_long_double: success = true; break; @@ -516,6 +1013,8 @@ Scalar::GetValueTypeAsCString (Scalar::Type type) case e_float: return "float"; case e_double: return "double"; case e_long_double: return "long double"; + case e_sint128: return "int128_t"; + case e_uint128: return "uint128_t"; } return "???"; } @@ -567,145 +1066,198 @@ Scalar::Cast(Scalar::Type type) break; case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: switch (type) { - case e_void: break; - case e_sint: success = true; break; - case e_uint: m_data.uint = m_data.sint; success = true; break; - case e_slong: m_data.slong = m_data.sint; success = true; break; - case e_ulong: m_data.ulong = m_data.sint; success = true; break; - case e_slonglong: m_data.slonglong = m_data.sint; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.sint; success = true; break; - case e_float: m_data.flt = m_data.sint; success = true; break; - case e_double: m_data.dbl = m_data.sint; success = true; break; - case e_long_double: m_data.ldbl = m_data.sint; success = true; break; + case e_void: break; + case e_sint: + { + m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + } + case e_uint: + { + m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + } + case e_slong: + { + m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + } + case e_ulong: + { + m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + } + case e_slonglong: + { + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + } + case e_ulonglong: + { + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + } + case e_sint128: + { + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + } + case e_uint128: + { + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + } + case e_float: + { + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + } + case e_double: + { + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + } + case e_long_double: + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); + success = true; + break; + } } break; - case e_uint: + case e_float: switch (type) { - case e_void: - case e_sint: m_data.sint = m_data.uint; success = true; break; - case e_uint: success = true; break; - case e_slong: m_data.slong = m_data.uint; success = true; break; - case e_ulong: m_data.ulong = m_data.uint; success = true; break; - case e_slonglong: m_data.slonglong = m_data.uint; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.uint; success = true; break; - case e_float: m_data.flt = m_data.uint; success = true; break; - case e_double: m_data.dbl = m_data.uint; success = true; break; - case e_long_double: m_data.ldbl = m_data.uint; success = true; break; + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: m_integer = m_float.bitcastToAPInt(); success = true; break; + case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; + case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; + case e_long_double: + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); + success = true; + break; } break; - case e_slong: + case e_double: switch (type) { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.slong; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.slong; success = true; break; - case e_slong: success = true; break; - case e_ulong: m_data.ulong = m_data.slong; success = true; break; - case e_slonglong: m_data.slonglong = m_data.slong; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.slong; success = true; break; - case e_float: m_data.flt = m_data.slong; success = true; break; - case e_double: m_data.dbl = m_data.slong; success = true; break; - case e_long_double: m_data.ldbl = m_data.slong; success = true; break; + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: m_integer = m_float.bitcastToAPInt(); success = true; break; + case e_float: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break; + case e_double: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break; + case e_long_double: + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); + success = true; + break; } break; - case e_ulong: + case e_long_double: switch (type) { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.ulong; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.ulong; success = true; break; - case e_slong: m_data.slong = m_data.ulong; success = true; break; - case e_ulong: success = true; break; - case e_slonglong: m_data.slonglong = m_data.ulong; success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.ulong; success = true; break; - case e_float: m_data.flt = m_data.ulong; success = true; break; - case e_double: m_data.dbl = m_data.ulong; success = true; break; - case e_long_double: m_data.ldbl = m_data.ulong; success = true; break; + case e_void: break; + case e_sint: + { + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; } - break; - - case e_slonglong: - switch (type) + case e_uint: { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.slonglong; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.slonglong; success = true; break; - case e_slong: m_data.slong = m_data.slonglong; success = true; break; - case e_ulong: m_data.ulong = m_data.slonglong; success = true; break; - case e_slonglong: success = true; break; - case e_ulonglong: m_data.ulonglong = m_data.slonglong; success = true; break; - case e_float: m_data.flt = m_data.slonglong; success = true; break; - case e_double: m_data.dbl = m_data.slonglong; success = true; break; - case e_long_double: m_data.ldbl = m_data.slonglong; success = true; break; + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; } - break; - - case e_ulonglong: - switch (type) + case e_slong: { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.ulonglong; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.ulonglong; success = true; break; - case e_slong: m_data.slong = m_data.ulonglong; success = true; break; - case e_ulong: m_data.ulong = m_data.ulonglong; success = true; break; - case e_slonglong: m_data.slonglong = m_data.ulonglong; success = true; break; - case e_ulonglong: success = true; break; - case e_float: m_data.flt = m_data.ulonglong; success = true; break; - case e_double: m_data.dbl = m_data.ulonglong; success = true; break; - case e_long_double: m_data.ldbl = m_data.ulonglong; success = true; break; + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; } - break; - - case e_float: - switch (type) + case e_ulong: { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.flt; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.flt; success = true; break; - case e_slong: m_data.slong = (slong_t)m_data.flt; success = true; break; - case e_ulong: m_data.ulong = (ulong_t)m_data.flt; success = true; break; - case e_slonglong: m_data.slonglong = (slonglong_t)m_data.flt; success = true; break; - case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.flt; success = true; break; - case e_float: success = true; break; - case e_double: m_data.dbl = m_data.flt; success = true; break; - case e_long_double: m_data.ldbl = m_data.flt; success = true; break; + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; } - break; - - case e_double: - switch (type) + case e_slonglong: { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.dbl; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.dbl; success = true; break; - case e_slong: m_data.slong = (slong_t)m_data.dbl; success = true; break; - case e_ulong: m_data.ulong = (ulong_t)m_data.dbl; success = true; break; - case e_slonglong: m_data.slonglong = (slonglong_t)m_data.dbl; success = true; break; - case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.dbl; success = true; break; - case e_float: m_data.flt = (float_t)m_data.dbl; success = true; break; - case e_double: success = true; break; - case e_long_double: m_data.ldbl = m_data.dbl; success = true; break; + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; } - break; - - case e_long_double: - switch (type) + case e_ulonglong: { - case e_void: - case e_sint: m_data.sint = (sint_t)m_data.ldbl; success = true; break; - case e_uint: m_data.uint = (uint_t)m_data.ldbl; success = true; break; - case e_slong: m_data.slong = (slong_t)m_data.ldbl; success = true; break; - case e_ulong: m_data.ulong = (ulong_t)m_data.ldbl; success = true; break; - case e_slonglong: m_data.slonglong = (slonglong_t)m_data.ldbl; success = true; break; - case e_ulonglong: m_data.ulonglong = (ulonglong_t)m_data.ldbl; success = true; break; - case e_float: m_data.flt = (float_t)m_data.ldbl; success = true; break; - case e_double: m_data.dbl = (double_t)m_data.ldbl; success = true; break; + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + } + case e_sint128: + { + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + } + case e_uint128: + { + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + } + case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; + case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; case e_long_double: success = true; break; } break; @@ -730,6 +1282,8 @@ Scalar::MakeSigned () case e_ulong: m_type = e_slong; success = true; break; case e_slonglong: success = true; break; case e_ulonglong: m_type = e_slonglong; success = true; break; + case e_sint128: success = true; break; + case e_uint128: m_type = e_sint; success = true; break; case e_float: success = true; break; case e_double: success = true; break; case e_long_double: success = true; break; @@ -738,131 +1292,241 @@ Scalar::MakeSigned () return success; } -int -Scalar::SInt(int fail_value) const +char +Scalar::SChar(char fail_value) const { switch (m_type) { case e_void: break; - case e_sint: return m_data.sint; - case e_uint: return (int)m_data.uint; - case e_slong: return (int)m_data.slong; - case e_ulong: return (int)m_data.ulong; - case e_slonglong: return (int)m_data.slonglong; - case e_ulonglong: return (int)m_data.ulonglong; - case e_float: return (int)m_data.flt; - case e_double: return (int)m_data.dbl; - case e_long_double: return (int)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const schar_t *)(m_integer.sextOrTrunc(sizeof(schar_t) * 8)).getRawData(); + case e_float: + return (schar_t)m_float.convertToFloat(); + case e_double: + return (schar_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (schar_t)*ldbl_val.getRawData(); } return fail_value; } -unsigned int -Scalar::UInt(unsigned int fail_value) const +unsigned char +Scalar::UChar(unsigned char fail_value) const { switch (m_type) { case e_void: break; - case e_sint: return (unsigned int)m_data.sint; - case e_uint: return (unsigned int)m_data.uint; - case e_slong: return (unsigned int)m_data.slong; - case e_ulong: return (unsigned int)m_data.ulong; - case e_slonglong: return (unsigned int)m_data.slonglong; - case e_ulonglong: return (unsigned int)m_data.ulonglong; - case e_float: return (unsigned int)m_data.flt; - case e_double: return (unsigned int)m_data.dbl; - case e_long_double: return (unsigned int)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const uchar_t *)m_integer.getRawData(); + case e_float: + return (uchar_t)m_float.convertToFloat(); + case e_double: + return (uchar_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (uchar_t)*ldbl_val.getRawData(); } return fail_value; } - -long -Scalar::SLong(long fail_value) const +short +Scalar::SShort(short fail_value) const { switch (m_type) { case e_void: break; - case e_sint: return (long)m_data.sint; - case e_uint: return (long)m_data.uint; - case e_slong: return (long)m_data.slong; - case e_ulong: return (long)m_data.ulong; - case e_slonglong: return (long)m_data.slonglong; - case e_ulonglong: return (long)m_data.ulonglong; - case e_float: return (long)m_data.flt; - case e_double: return (long)m_data.dbl; - case e_long_double: return (long)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const sshort_t *)(m_integer.sextOrTrunc(sizeof(sshort_t) * 8)).getRawData(); + case e_float: + return (sshort_t)m_float.convertToFloat(); + case e_double: + return (sshort_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const sshort_t *)ldbl_val.getRawData(); } return fail_value; } - - -unsigned long -Scalar::ULong(unsigned long fail_value) const +unsigned short +Scalar::UShort(unsigned short fail_value) const { switch (m_type) { case e_void: break; - case e_sint: return (unsigned long)m_data.sint; - case e_uint: return (unsigned long)m_data.uint; - case e_slong: return (unsigned long)m_data.slong; - case e_ulong: return (unsigned long)m_data.ulong; - case e_slonglong: return (unsigned long)m_data.slonglong; - case e_ulonglong: return (unsigned long)m_data.ulonglong; - case e_float: return (unsigned long)m_data.flt; - case e_double: return (unsigned long)m_data.dbl; - case e_long_double: return (unsigned long)m_data.ldbl; - } - return fail_value; -} - -uint64_t -Scalar::GetRawBits64(uint64_t fail_value) const -{ - switch (m_type) - { - case e_void: - break; - case e_sint: case e_uint: - return m_data.uint; - case e_slong: case e_ulong: - return m_data.ulong; - case e_slonglong: case e_ulonglong: - return m_data.ulonglong; - + case e_sint128: + case e_uint128: + return *(const ushort_t *)m_integer.getRawData(); case e_float: - if (sizeof(m_data.flt) == sizeof(m_data.uint)) - return m_data.uint; - else if (sizeof(m_data.flt) == sizeof(m_data.ulong)) - return m_data.ulong; - else if (sizeof(m_data.flt) == sizeof(m_data.ulonglong)) - return m_data.ulonglong; - break; + return (ushort_t)m_float.convertToFloat(); + case e_double: + return (ushort_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const ushort_t *)ldbl_val.getRawData();; + } + return fail_value; +} +int +Scalar::SInt(int fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const sint_t *)(m_integer.sextOrTrunc(sizeof(sint_t) * 8)).getRawData(); + case e_float: + return (sint_t)m_float.convertToFloat(); case e_double: - if (sizeof(m_data.dbl) == sizeof(m_data.uint)) - return m_data.uint; - else if (sizeof(m_data.dbl) == sizeof(m_data.ulong)) - return m_data.ulong; - else if (sizeof(m_data.dbl) == sizeof(m_data.ulonglong)) - return m_data.ulonglong; - break; + return (sint_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const sint_t *)ldbl_val.getRawData(); + } + return fail_value; +} + +unsigned int +Scalar::UInt(unsigned int fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const uint_t *)m_integer.getRawData(); + case e_float: + return (uint_t)m_float.convertToFloat(); + case e_double: + return (uint_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const uint_t *)ldbl_val.getRawData(); + } + return fail_value; +} + + +long +Scalar::SLong(long fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const slong_t *)(m_integer.sextOrTrunc(sizeof(slong_t) * 8)).getRawData(); + case e_float: + return (slong_t)m_float.convertToFloat(); + case e_double: + return (slong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const slong_t *)ldbl_val.getRawData(); + } + return fail_value; +} + + +unsigned long +Scalar::ULong(unsigned long fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const ulong_t *)m_integer.getRawData(); + case e_float: + return (ulong_t)m_float.convertToFloat(); + case e_double: + return (ulong_t)m_float.convertToDouble(); case e_long_double: - if (sizeof(m_data.ldbl) == sizeof(m_data.uint)) - return m_data.uint; - else if (sizeof(m_data.ldbl) == sizeof(m_data.ulong)) - return m_data.ulong; - else if (sizeof(m_data.ldbl) == sizeof(m_data.ulonglong)) - return m_data.ulonglong; + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const ulong_t *)ldbl_val.getRawData(); + } + return fail_value; +} + +uint64_t +Scalar::GetRawBits64(uint64_t fail_value) const +{ + switch (m_type) + { + case e_void: break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *m_integer.getRawData(); + case e_float: + return (uint64_t)m_float.convertToFloat(); + case e_double: + return (uint64_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *ldbl_val.getRawData(); } return fail_value; } @@ -875,15 +1539,22 @@ Scalar::SLongLong(long long fail_value) const switch (m_type) { case e_void: break; - case e_sint: return (long long)m_data.sint; - case e_uint: return (long long)m_data.uint; - case e_slong: return (long long)m_data.slong; - case e_ulong: return (long long)m_data.ulong; - case e_slonglong: return (long long)m_data.slonglong; - case e_ulonglong: return (long long)m_data.ulonglong; - case e_float: return (long long)m_data.flt; - case e_double: return (long long)m_data.dbl; - case e_long_double: return (long long)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const slonglong_t *)(m_integer.sextOrTrunc(sizeof(slonglong_t) * 8)).getRawData(); + case e_float: + return (slonglong_t)m_float.convertToFloat(); + case e_double: + return (slonglong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const slonglong_t *)ldbl_val.getRawData(); } return fail_value; } @@ -895,19 +1566,71 @@ Scalar::ULongLong(unsigned long long fail_value) const switch (m_type) { case e_void: break; - case e_sint: return (unsigned long long)m_data.sint; - case e_uint: return (unsigned long long)m_data.uint; - case e_slong: return (unsigned long long)m_data.slong; - case e_ulong: return (unsigned long long)m_data.ulong; - case e_slonglong: return (unsigned long long)m_data.slonglong; - case e_ulonglong: return (unsigned long long)m_data.ulonglong; - case e_float: return (unsigned long long)m_data.flt; - case e_double: return (unsigned long long)m_data.dbl; - case e_long_double: return (unsigned long long)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return *(const ulonglong_t *)m_integer.getRawData(); + case e_float: + return (ulonglong_t)m_float.convertToFloat(); + case e_double: + return (ulonglong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return *(const ulonglong_t *)ldbl_val.getRawData(); } return fail_value; } +llvm::APInt +Scalar::UInt128(const llvm::APInt& fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} + +llvm::APInt +Scalar::SInt128(llvm::APInt& fail_value) const +{ + switch (m_type) + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} float Scalar::Float(float fail_value) const @@ -915,15 +1638,22 @@ Scalar::Float(float fail_value) const switch (m_type) { case e_void: break; - case e_sint: return (float)m_data.sint; - case e_uint: return (float)m_data.uint; - case e_slong: return (float)m_data.slong; - case e_ulong: return (float)m_data.ulong; - case e_slonglong: return (float)m_data.slonglong; - case e_ulonglong: return (float)m_data.ulonglong; - case e_float: return (float)m_data.flt; - case e_double: return (float)m_data.dbl; - case e_long_double: return (float)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return m_integer.bitsToFloat(); + case e_float: + return m_float.convertToFloat(); + case e_double: + return (float_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return ldbl_val.bitsToFloat(); } return fail_value; } @@ -935,15 +1665,22 @@ Scalar::Double(double fail_value) const switch (m_type) { case e_void: break; - case e_sint: return (double)m_data.sint; - case e_uint: return (double)m_data.uint; - case e_slong: return (double)m_data.slong; - case e_ulong: return (double)m_data.ulong; - case e_slonglong: return (double)m_data.slonglong; - case e_ulonglong: return (double)m_data.ulonglong; - case e_float: return (double)m_data.flt; - case e_double: return (double)m_data.dbl; - case e_long_double: return (double)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return m_integer.bitsToDouble(); + case e_float: + return (double_t)m_float.convertToFloat(); + case e_double: + return m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return ldbl_val.bitsToFloat(); } return fail_value; } @@ -955,15 +1692,22 @@ Scalar::LongDouble(long double fail_value) const switch (m_type) { case e_void: break; - case e_sint: return (long double)m_data.sint; - case e_uint: return (long double)m_data.uint; - case e_slong: return (long double)m_data.slong; - case e_ulong: return (long double)m_data.ulong; - case e_slonglong: return (long double)m_data.slonglong; - case e_ulonglong: return (long double)m_data.ulonglong; - case e_float: return (long double)m_data.flt; - case e_double: return (long double)m_data.dbl; - case e_long_double: return (long double)m_data.ldbl; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + return (long_double_t)m_integer.bitsToDouble(); + case e_float: + return (long_double_t)m_float.convertToFloat(); + case e_double: + return (long_double_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (long_double_t)ldbl_val.bitsToDouble(); } return fail_value; } @@ -978,17 +1722,27 @@ Scalar::operator+= (const Scalar& rhs) if ((m_type = PromoteToMaxType(*this, rhs, temp_value, a, b)) != Scalar::e_void) { switch (m_type) - { - case e_void: break; - case e_sint: m_data.sint = a->m_data.sint + b->m_data.sint; break; - case e_uint: m_data.uint = a->m_data.uint + b->m_data.uint; break; - case e_slong: m_data.slong = a->m_data.slong + b->m_data.slong; break; - case e_ulong: m_data.ulong = a->m_data.ulong + b->m_data.ulong; break; - case e_slonglong: m_data.slonglong = a->m_data.slonglong + b->m_data.slonglong; break; - case e_ulonglong: m_data.ulonglong = a->m_data.ulonglong + b->m_data.ulonglong; break; - case e_float: m_data.flt = a->m_data.flt + b->m_data.flt; break; - case e_double: m_data.dbl = a->m_data.dbl + b->m_data.dbl; break; - case e_long_double: m_data.ldbl = a->m_data.ldbl + b->m_data.ldbl; break; + { + case e_void: break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + { + m_integer = a->m_integer + b->m_integer; + break; + } + case e_float: + case e_double: + case e_long_double: + { + m_float = a->m_float + b->m_float; + break; + } } } return *this; @@ -1007,109 +1761,33 @@ Scalar::operator<<= (const Scalar& rhs) break; case e_sint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.sint <<= rhs.m_data.sint; break; - case e_uint: m_data.sint <<= rhs.m_data.uint; break; - case e_slong: m_data.sint <<= rhs.m_data.slong; break; - case e_ulong: m_data.sint <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.sint <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.sint <<= rhs.m_data.ulonglong; break; - } - break; - case e_uint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.uint <<= rhs.m_data.sint; break; - case e_uint: m_data.uint <<= rhs.m_data.uint; break; - case e_slong: m_data.uint <<= rhs.m_data.slong; break; - case e_ulong: m_data.uint <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.uint <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.uint <<= rhs.m_data.ulonglong; break; - } - break; - case e_slong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slong <<= rhs.m_data.sint; break; - case e_uint: m_data.slong <<= rhs.m_data.uint; break; - case e_slong: m_data.slong <<= rhs.m_data.slong; break; - case e_ulong: m_data.slong <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.slong <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slong <<= rhs.m_data.ulonglong; break; - } - break; - case e_ulong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.ulong <<= rhs.m_data.sint; break; - case e_uint: m_data.ulong <<= rhs.m_data.uint; break; - case e_slong: m_data.ulong <<= rhs.m_data.slong; break; - case e_ulong: m_data.ulong <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulong <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulong <<= rhs.m_data.ulonglong; break; - } - break; case e_slonglong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slonglong <<= rhs.m_data.sint; break; - case e_uint: m_data.slonglong <<= rhs.m_data.uint; break; - case e_slong: m_data.slonglong <<= rhs.m_data.slong; break; - case e_ulong: m_data.slonglong <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.slonglong <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slonglong <<= rhs.m_data.ulonglong; break; - } - break; - case e_ulonglong: + case e_sint128: + case e_uint128: switch (rhs.m_type) { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.ulonglong <<= rhs.m_data.sint; break; - case e_uint: m_data.ulonglong <<= rhs.m_data.uint; break; - case e_slong: m_data.ulonglong <<= rhs.m_data.slong; break; - case e_ulong: m_data.ulonglong <<= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulonglong <<= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulonglong <<= rhs.m_data.ulonglong; break; + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + { + m_integer <<= *rhs.m_integer.getRawData(); + break; + } } break; } @@ -1130,44 +1808,12 @@ Scalar::ShiftRightLogical(const Scalar& rhs) case e_sint: case e_uint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.uint >>= rhs.m_data.sint; break; - case e_uint: m_data.uint >>= rhs.m_data.uint; break; - case e_slong: m_data.uint >>= rhs.m_data.slong; break; - case e_ulong: m_data.uint >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.uint >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.uint >>= rhs.m_data.ulonglong; break; - } - break; - case e_slong: case e_ulong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.ulong >>= rhs.m_data.sint; break; - case e_uint: m_data.ulong >>= rhs.m_data.uint; break; - case e_slong: m_data.ulong >>= rhs.m_data.slong; break; - case e_ulong: m_data.ulong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulong >>= rhs.m_data.ulonglong; break; - } - break; - case e_slonglong: case e_ulonglong: + case e_sint128: + case e_uint128: switch (rhs.m_type) { case e_void: @@ -1176,12 +1822,15 @@ Scalar::ShiftRightLogical(const Scalar& rhs) case e_long_double: m_type = e_void; break; - case e_sint: m_data.ulonglong >>= rhs.m_data.sint; break; - case e_uint: m_data.ulonglong >>= rhs.m_data.uint; break; - case e_slong: m_data.ulonglong >>= rhs.m_data.slong; break; - case e_ulong: m_data.ulonglong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulonglong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulonglong >>= rhs.m_data.ulonglong; break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + m_integer = m_integer.lshr(*(const uint_t *) rhs.m_integer.getRawData()); break; } break; } @@ -1202,95 +1851,13 @@ Scalar::operator>>= (const Scalar& rhs) break; case e_sint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.sint >>= rhs.m_data.sint; break; - case e_uint: m_data.sint >>= rhs.m_data.uint; break; - case e_slong: m_data.sint >>= rhs.m_data.slong; break; - case e_ulong: m_data.sint >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.sint >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.sint >>= rhs.m_data.ulonglong; break; - } - break; - case e_uint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.uint >>= rhs.m_data.sint; break; - case e_uint: m_data.uint >>= rhs.m_data.uint; break; - case e_slong: m_data.uint >>= rhs.m_data.slong; break; - case e_ulong: m_data.uint >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.uint >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.uint >>= rhs.m_data.ulonglong; break; - } - break; - case e_slong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slong >>= rhs.m_data.sint; break; - case e_uint: m_data.slong >>= rhs.m_data.uint; break; - case e_slong: m_data.slong >>= rhs.m_data.slong; break; - case e_ulong: m_data.slong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.slong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slong >>= rhs.m_data.ulonglong; break; - } - break; - case e_ulong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.ulong >>= rhs.m_data.sint; break; - case e_uint: m_data.ulong >>= rhs.m_data.uint; break; - case e_slong: m_data.ulong >>= rhs.m_data.slong; break; - case e_ulong: m_data.ulong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulong >>= rhs.m_data.ulonglong; break; - } - break; case e_slonglong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slonglong >>= rhs.m_data.sint; break; - case e_uint: m_data.slonglong >>= rhs.m_data.uint; break; - case e_slong: m_data.slonglong >>= rhs.m_data.slong; break; - case e_ulong: m_data.slonglong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.slonglong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slonglong >>= rhs.m_data.ulonglong; break; - } - break; - case e_ulonglong: + case e_sint128: + case e_uint128: switch (rhs.m_type) { case e_void: @@ -1299,12 +1866,18 @@ Scalar::operator>>= (const Scalar& rhs) case e_long_double: m_type = e_void; break; - case e_sint: m_data.ulonglong >>= rhs.m_data.sint; break; - case e_uint: m_data.ulonglong >>= rhs.m_data.uint; break; - case e_slong: m_data.ulonglong >>= rhs.m_data.slong; break; - case e_ulong: m_data.ulonglong >>= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulonglong >>= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulonglong >>= rhs.m_data.ulonglong; break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + { + m_integer >> *rhs.m_integer.getRawData(); + break; + } } break; } @@ -1316,104 +1889,22 @@ Scalar& Scalar::operator&= (const Scalar& rhs) { switch (m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - - case e_sint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.sint &= rhs.m_data.sint; break; - case e_uint: m_data.sint &= rhs.m_data.uint; break; - case e_slong: m_data.sint &= rhs.m_data.slong; break; - case e_ulong: m_data.sint &= rhs.m_data.ulong; break; - case e_slonglong: m_data.sint &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.sint &= rhs.m_data.ulonglong; break; - } - break; - - case e_uint: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.uint &= rhs.m_data.sint; break; - case e_uint: m_data.uint &= rhs.m_data.uint; break; - case e_slong: m_data.uint &= rhs.m_data.slong; break; - case e_ulong: m_data.uint &= rhs.m_data.ulong; break; - case e_slonglong: m_data.uint &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.uint &= rhs.m_data.ulonglong; break; - } - break; - - case e_slong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slong &= rhs.m_data.sint; break; - case e_uint: m_data.slong &= rhs.m_data.uint; break; - case e_slong: m_data.slong &= rhs.m_data.slong; break; - case e_ulong: m_data.slong &= rhs.m_data.ulong; break; - case e_slonglong: m_data.slong &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slong &= rhs.m_data.ulonglong; break; - } - break; - - case e_ulong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.ulong &= rhs.m_data.sint; break; - case e_uint: m_data.ulong &= rhs.m_data.uint; break; - case e_slong: m_data.ulong &= rhs.m_data.slong; break; - case e_ulong: m_data.ulong &= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulong &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulong &= rhs.m_data.ulonglong; break; - } - break; - case e_slonglong: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: m_data.slonglong &= rhs.m_data.sint; break; - case e_uint: m_data.slonglong &= rhs.m_data.uint; break; - case e_slong: m_data.slonglong &= rhs.m_data.slong; break; - case e_ulong: m_data.slonglong &= rhs.m_data.ulong; break; - case e_slonglong: m_data.slonglong &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.slonglong &= rhs.m_data.ulonglong; break; - } + { + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: case e_ulonglong: + case e_sint128: + case e_uint128: switch (rhs.m_type) { case e_void: @@ -1422,12 +1913,18 @@ Scalar::operator&= (const Scalar& rhs) case e_long_double: m_type = e_void; break; - case e_sint: m_data.ulonglong &= rhs.m_data.sint; break; - case e_uint: m_data.ulonglong &= rhs.m_data.uint; break; - case e_slong: m_data.ulonglong &= rhs.m_data.slong; break; - case e_ulong: m_data.ulonglong &= rhs.m_data.ulong; break; - case e_slonglong: m_data.ulonglong &= rhs.m_data.slonglong; break; - case e_ulonglong: m_data.ulonglong &= rhs.m_data.ulonglong; break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + { + m_integer &= rhs.m_integer; + break; + } } break; } @@ -1445,26 +1942,22 @@ Scalar::AbsoluteValue() break; case e_sint: - if (m_data.sint < 0) - m_data.sint = -m_data.sint; - return true; - case e_slong: - if (m_data.slong < 0) - m_data.slong = -m_data.slong; - return true; - case e_slonglong: - if (m_data.slonglong < 0) - m_data.slonglong = -m_data.slonglong; + case e_sint128: + if (m_integer.isNegative()) + m_integer = -m_integer; return true; case e_uint: case e_ulong: case e_ulonglong: return true; - case e_float: m_data.flt = fabsf(m_data.flt); return true; - case e_double: m_data.dbl = fabs(m_data.dbl); return true; - case e_long_double: m_data.ldbl = fabsl(m_data.ldbl); return true; + case e_uint128: + case e_float: + case e_double: + case e_long_double: + m_float.clearSign(); + return true; } return false; } @@ -1476,15 +1969,19 @@ Scalar::UnaryNegate() switch (m_type) { case e_void: break; - case e_sint: m_data.sint = -m_data.sint; return true; - case e_uint: m_data.uint = -m_data.uint; return true; - case e_slong: m_data.slong = -m_data.slong; return true; - case e_ulong: m_data.ulong = -m_data.ulong; return true; - case e_slonglong: m_data.slonglong = -m_data.slonglong; return true; - case e_ulonglong: m_data.ulonglong = -m_data.ulonglong; return true; - case e_float: m_data.flt = -m_data.flt; return true; - case e_double: m_data.dbl = -m_data.dbl; return true; - case e_long_double: m_data.ldbl = -m_data.ldbl; return true; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + m_integer = -m_integer; return true; + case e_float: + case e_double: + case e_long_double: + m_float.changeSign(); return true; } return false; } @@ -1494,12 +1991,15 @@ Scalar::OnesComplement() { switch (m_type) { - case e_sint: m_data.sint = ~m_data.sint; return true; - case e_uint: m_data.uint = ~m_data.uint; return true; - case e_slong: m_data.slong = ~m_data.slong; return true; - case e_ulong: m_data.ulong = ~m_data.ulong; return true; - case e_slonglong: m_data.slonglong = ~m_data.slonglong; return true; - case e_ulonglong: m_data.ulonglong = ~m_data.ulonglong; return true; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + m_integer = ~m_integer; return true; case e_void: case e_float: @@ -1523,15 +2023,19 @@ lldb_private::operator+ (const Scalar& lhs, const Scalar& rhs) switch (result.m_type) { case Scalar::e_void: break; - case Scalar::e_sint: result.m_data.sint = a->m_data.sint + b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint + b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong + b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong + b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong + b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong + b->m_data.ulonglong; break; - case Scalar::e_float: result.m_data.flt = a->m_data.flt + b->m_data.flt; break; - case Scalar::e_double: result.m_data.dbl = a->m_data.dbl + b->m_data.dbl; break; - case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl + b->m_data.ldbl; 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: + result.m_integer = a->m_integer + b->m_integer; break; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result.m_float = a->m_float + b->m_float; break; } } return result; @@ -1550,15 +2054,19 @@ lldb_private::operator- (const Scalar& lhs, const Scalar& rhs) switch (result.m_type) { case Scalar::e_void: break; - case Scalar::e_sint: result.m_data.sint = a->m_data.sint - b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint - b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong - b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong - b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong - b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong - b->m_data.ulonglong; break; - case Scalar::e_float: result.m_data.flt = a->m_data.flt - b->m_data.flt; break; - case Scalar::e_double: result.m_data.dbl = a->m_data.dbl - b->m_data.dbl; break; - case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl - b->m_data.ldbl; 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: + result.m_integer = a->m_integer - b->m_integer; break; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result.m_float = a->m_float - b->m_float; break; } } return result; @@ -1576,16 +2084,31 @@ lldb_private::operator/ (const Scalar& lhs, const Scalar& rhs) switch (result.m_type) { case Scalar::e_void: break; - - case Scalar::e_sint: if (b->m_data.sint != 0) { result.m_data.sint = a->m_data.sint/ b->m_data.sint; return result; } break; - case Scalar::e_uint: if (b->m_data.uint != 0) { result.m_data.uint = a->m_data.uint / b->m_data.uint; return result; } break; - case Scalar::e_slong: if (b->m_data.slong != 0) { result.m_data.slong = a->m_data.slong / b->m_data.slong; return result; } break; - case Scalar::e_ulong: if (b->m_data.ulong != 0) { result.m_data.ulong = a->m_data.ulong / b->m_data.ulong; return result; } break; - case Scalar::e_slonglong: if (b->m_data.slonglong != 0) { result.m_data.slonglong = a->m_data.slonglong / b->m_data.slonglong; return result; } break; - case Scalar::e_ulonglong: if (b->m_data.ulonglong != 0) { result.m_data.ulonglong = a->m_data.ulonglong / b->m_data.ulonglong; return result; } break; - case Scalar::e_float: if (b->m_data.flt != 0.0f) { result.m_data.flt = a->m_data.flt / b->m_data.flt; return result; } break; - case Scalar::e_double: if (b->m_data.dbl != 0.0) { result.m_data.dbl = a->m_data.dbl / b->m_data.dbl; return result; } break; - case Scalar::e_long_double: if (b->m_data.ldbl != 0.0) { result.m_data.ldbl = a->m_data.ldbl / b->m_data.ldbl; return result; } 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: + { + if (b->m_integer != 0) + { + result.m_integer = *a->m_integer.getRawData() / *b->m_integer.getRawData(); + return result; + } + break; + } + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + if (b->m_float.isZero()) + { + result.m_float = a->m_float / b->m_float; + return result; + } + break; } } // For division only, the only way it should make it here is if a promotion failed, @@ -1606,15 +2129,19 @@ lldb_private::operator* (const Scalar& lhs, const Scalar& rhs) switch (result.m_type) { case Scalar::e_void: break; - case Scalar::e_sint: result.m_data.sint = a->m_data.sint * b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint * b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong * b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong * b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong * b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong * b->m_data.ulonglong; break; - case Scalar::e_float: result.m_data.flt = a->m_data.flt * b->m_data.flt; break; - case Scalar::e_double: result.m_data.dbl = a->m_data.dbl * b->m_data.dbl; break; - case Scalar::e_long_double: result.m_data.ldbl = a->m_data.ldbl * b->m_data.ldbl; 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: + result.m_integer = a->m_integer * b->m_integer; break; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result.m_float = a->m_float * b->m_float; break; } } return result; @@ -1631,13 +2158,15 @@ lldb_private::operator& (const Scalar& lhs, const Scalar& rhs) { switch (result.m_type) { - case Scalar::e_sint: result.m_data.sint = a->m_data.sint & b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint & b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong & b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong & b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong & b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong & b->m_data.ulonglong; 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: + result.m_integer = a->m_integer & b->m_integer; break; case Scalar::e_void: case Scalar::e_float: case Scalar::e_double: @@ -1661,12 +2190,15 @@ lldb_private::operator| (const Scalar& lhs, const Scalar& rhs) { switch (result.m_type) { - case Scalar::e_sint: result.m_data.sint = a->m_data.sint | b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint | b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong | b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong | b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong | b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong | b->m_data.ulonglong; 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: + result.m_integer = a->m_integer | b->m_integer; break; case Scalar::e_void: case Scalar::e_float: @@ -1692,12 +2224,23 @@ lldb_private::operator% (const Scalar& lhs, const Scalar& rhs) switch (result.m_type) { default: break; - case Scalar::e_sint: if (b->m_data.sint != 0) { result.m_data.sint = a->m_data.sint % b->m_data.sint; return result; } break; - case Scalar::e_uint: if (b->m_data.uint != 0) { result.m_data.uint = a->m_data.uint % b->m_data.uint; return result; } break; - case Scalar::e_slong: if (b->m_data.slong != 0) { result.m_data.slong = a->m_data.slong % b->m_data.slong; return result; } break; - case Scalar::e_ulong: if (b->m_data.ulong != 0) { result.m_data.ulong = a->m_data.ulong % b->m_data.ulong; return result; } break; - case Scalar::e_slonglong: if (b->m_data.slonglong != 0) { result.m_data.slonglong = a->m_data.slonglong % b->m_data.slonglong; return result; } break; - case Scalar::e_ulonglong: if (b->m_data.ulonglong != 0) { result.m_data.ulonglong = a->m_data.ulonglong % b->m_data.ulonglong; return result; } break; + 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: + { + if (b->m_integer != 0) + { + result.m_integer = *a->m_integer.getRawData() % *b->m_integer.getRawData(); + return result; + } + break; + } } } result.m_type = Scalar::e_void; @@ -1715,12 +2258,15 @@ lldb_private::operator^ (const Scalar& lhs, const Scalar& rhs) { switch (result.m_type) { - case Scalar::e_sint: result.m_data.sint = a->m_data.sint ^ b->m_data.sint; break; - case Scalar::e_uint: result.m_data.uint = a->m_data.uint ^ b->m_data.uint; break; - case Scalar::e_slong: result.m_data.slong = a->m_data.slong ^ b->m_data.slong; break; - case Scalar::e_ulong: result.m_data.ulong = a->m_data.ulong ^ b->m_data.ulong; break; - case Scalar::e_slonglong: result.m_data.slonglong = a->m_data.slonglong ^ b->m_data.slonglong; break; - case Scalar::e_ulonglong: result.m_data.ulonglong = a->m_data.ulonglong ^ b->m_data.ulonglong; 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: + result.m_integer = a->m_integer ^ b->m_integer; break; case Scalar::e_void: case Scalar::e_float: @@ -1754,21 +2300,21 @@ lldb_private::operator>> (const Scalar& lhs, const Scalar &rhs) unsigned int Scalar::RawUInt () const { - return m_data.uint; + return *(const uint_t *) m_integer.getRawData(); } // Return the raw unsigned long without any casting or conversion unsigned long Scalar::RawULong () const { - return m_data.ulong; + return *(const ulong_t *) m_integer.getRawData(); } // Return the raw unsigned long long without any casting or conversion unsigned long long Scalar::RawULongLong () const { - return m_data.ulonglong; + return *(const ulonglong_t *) m_integer.getRawData(); } @@ -1801,9 +2347,9 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize (byte_size); switch (m_type) { - case e_uint: m_data.uint = (uint_t)uval64; break; - case e_ulong: m_data.ulong = (ulong_t)uval64; break; - case e_ulonglong: m_data.ulonglong = (ulonglong_t)uval64; break; + case e_uint: m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false); break; + case e_ulong: m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false); break; + case e_ulonglong: m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false); break; default: error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size); break; @@ -1830,9 +2376,9 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize (byte_size); switch (m_type) { - case e_sint: m_data.sint = (sint_t)sval64; break; - case e_slong: m_data.slong = (slong_t)sval64; break; - case e_slonglong: m_data.slonglong = (slonglong_t)sval64; break; + case e_sint: m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true); break; + case e_slong: m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true); break; + case e_slonglong: m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true); break; default: error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size); break; @@ -1847,24 +2393,36 @@ Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t by break; case eEncodingIEEE754: + static float f_val; + static double d_val; + static long double l_val; if (byte_size == sizeof (float)) { - if (::sscanf (value_str, "%f", &m_data.flt) == 1) + if (::sscanf (value_str, "%f", &f_val) == 1) + { + m_float = llvm::APFloat(f_val); m_type = e_float; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof (double)) { - if (::sscanf (value_str, "%lf", &m_data.dbl) == 1) + if (::sscanf (value_str, "%lf", &d_val) == 1) + { + m_float = llvm::APFloat(d_val); m_type = e_double; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } else if (byte_size == sizeof (long double)) { - if (::sscanf (value_str, "%Lf", &m_data.ldbl) == 1) + if (::sscanf (value_str, "%Lf", &l_val) == 1) + { + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&l_val)->x)); m_type = e_long_double; + } else error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); } @@ -1890,6 +2448,7 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b { Error error; + type128 int128; switch (encoding) { case lldb::eEncodingInvalid: @@ -1904,10 +2463,25 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b switch (byte_size) { - case 1: operator=((uint8_t)data.GetU8(&offset)); break; - case 2: operator=((uint16_t)data.GetU16(&offset)); break; - case 4: operator=((uint32_t)data.GetU32(&offset)); break; - case 8: operator=((uint64_t)data.GetU64(&offset)); break; + case 1: operator=((uint8_t)data.GetU8(&offset)); break; + case 2: operator=((uint16_t)data.GetU16(&offset)); break; + case 4: operator=((uint32_t)data.GetU32(&offset)); break; + case 8: operator=((uint64_t)data.GetU64(&offset)); break; + case 16: + { + if (data.GetByteOrder() == eByteOrderBig) + { + int128.x[1] = (uint64_t)data.GetU64 (&offset); + int128.x[0] = (uint64_t)data.GetU64 (&offset + 1); + } + else + { + int128.x[0] = (uint64_t)data.GetU64 (&offset); + int128.x[1] = (uint64_t)data.GetU64 (&offset + 1); + } + operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); + break; + } default: error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size); break; @@ -1924,6 +2498,21 @@ Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t b case 2: operator=((int16_t)data.GetU16(&offset)); break; case 4: operator=((int32_t)data.GetU32(&offset)); break; case 8: operator=((int64_t)data.GetU64(&offset)); break; + case 16: + { + if (data.GetByteOrder() == eByteOrderBig) + { + int128.x[1] = (uint64_t)data.GetU64 (&offset); + int128.x[0] = (uint64_t)data.GetU64 (&offset + 1); + } + else + { + int128.x[0] = (uint64_t)data.GetU64 (&offset); + int128.x[1] = (uint64_t)data.GetU64 (&offset + 1); + } + operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); + break; + } default: error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size); break; @@ -1966,47 +2555,22 @@ Scalar::SignExtend (uint32_t sign_bit_pos) case Scalar::e_sint: case Scalar::e_uint: - if (max_bit_pos == sign_bit_pos) - return true; - else if (sign_bit_pos < (max_bit_pos-1)) - { - unsigned int sign_bit = 1u << sign_bit_pos; - if (m_data.uint & sign_bit) - { - const unsigned int mask = ~(sign_bit) + 1u; - m_data.uint |= mask; - } - return true; - } - break; - case Scalar::e_slong: case Scalar::e_ulong: - if (max_bit_pos == sign_bit_pos) - return true; - else if (sign_bit_pos < (max_bit_pos-1)) - { - unsigned long sign_bit = 1ul << sign_bit_pos; - if (m_data.ulong & sign_bit) - { - const unsigned long mask = ~(sign_bit) + 1ul; - m_data.ulong |= mask; - } - return true; - } - break; - case Scalar::e_slonglong: case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: if (max_bit_pos == sign_bit_pos) return true; else if (sign_bit_pos < (max_bit_pos-1)) { - unsigned long long sign_bit = 1ull << sign_bit_pos; - if (m_data.ulonglong & sign_bit) + llvm::APInt sign_bit = llvm::APInt::getSignBit(sign_bit_pos + 1); + llvm::APInt bitwize_and = m_integer & sign_bit; + if (bitwize_and.getBoolValue()) { - const unsigned long long mask = ~(sign_bit) + 1ull; - m_data.ulonglong |= mask; + const llvm::APInt mask = ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1); + m_integer |= mask; } return true; } @@ -2053,66 +2617,40 @@ Scalar::ExtractBitfield (uint32_t bit_size, uint32_t msbit = bit_offset + bit_size - 1; uint32_t lsbit = bit_offset; + uint64_t result; switch (m_type) { case Scalar::e_void: break; case e_float: - if (sizeof(m_data.flt) == sizeof(sint_t)) - m_data.sint = (sint_t)SignedBits (m_data.sint, msbit, lsbit); - else if (sizeof(m_data.flt) == sizeof(ulong_t)) - m_data.slong = (slong_t)SignedBits (m_data.slong, msbit, lsbit); - else if (sizeof(m_data.flt) == sizeof(ulonglong_t)) - m_data.slonglong = (slonglong_t)SignedBits (m_data.slonglong, msbit, lsbit); - else - return false; + result = SignedBits ((uint64_t )m_float.convertToFloat(), msbit, lsbit); + m_float = llvm::APFloat((float_t)result); return true; - case e_double: - if (sizeof(m_data.dbl) == sizeof(sint_t)) - m_data.sint = SignedBits (m_data.sint, msbit, lsbit); - else if (sizeof(m_data.dbl) == sizeof(ulong_t)) - m_data.slong = SignedBits (m_data.slong, msbit, lsbit); - else if (sizeof(m_data.dbl) == sizeof(ulonglong_t)) - m_data.slonglong = SignedBits (m_data.slonglong, msbit, lsbit); - else - return false; - return true; - + result = SignedBits ((uint64_t )m_float.convertToDouble(), msbit, lsbit); + m_float = llvm::APFloat((double_t)result); case e_long_double: - if (sizeof(m_data.ldbl) == sizeof(sint_t)) - m_data.sint = SignedBits (m_data.sint, msbit, lsbit); - else if (sizeof(m_data.ldbl) == sizeof(ulong_t)) - m_data.slong = SignedBits (m_data.slong, msbit, lsbit); - else if (sizeof(m_data.ldbl) == sizeof(ulonglong_t)) - m_data.slonglong = SignedBits (m_data.slonglong, msbit, lsbit); + m_integer = m_float.bitcastToAPInt(); + result = SignedBits (*m_integer.getRawData(), msbit, lsbit); + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&result)->x)); else - return false; + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&result)->x)); return true; case Scalar::e_sint: - m_data.sint = (sint_t)SignedBits (m_data.sint, msbit, lsbit); - return true; - - case Scalar::e_uint: - m_data.uint = (uint_t)UnsignedBits (m_data.uint, msbit, lsbit); - return true; - case Scalar::e_slong: - m_data.slong = (slong_t)SignedBits (m_data.slong, msbit, lsbit); - return true; - - case Scalar::e_ulong: - m_data.ulong = (ulong_t)UnsignedBits (m_data.ulong, msbit, lsbit); - return true; - case Scalar::e_slonglong: - m_data.slonglong = (slonglong_t)SignedBits (m_data.slonglong, msbit, lsbit); + case Scalar::e_sint128: + m_integer = SignedBits (*m_integer.getRawData(), msbit, lsbit); return true; + case Scalar::e_uint: + case Scalar::e_ulong: case Scalar::e_ulonglong: - m_data.ulonglong = (ulonglong_t)UnsignedBits (m_data.ulonglong, msbit, lsbit); + case Scalar::e_uint128: + m_integer = UnsignedBits (*m_integer.getRawData(), msbit, lsbit); return true; } return false; @@ -2132,18 +2670,25 @@ lldb_private::operator== (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint == b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint == b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong == b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong == b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong == b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong == b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt == b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl == b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl == b->m_data.ldbl; + 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: + 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 false; } @@ -2158,18 +2703,25 @@ lldb_private::operator!= (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint != b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint != b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong != b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong != b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong != b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong != b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt != b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl != b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl != b->m_data.ldbl; + 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: + 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; } @@ -2183,18 +2735,26 @@ lldb_private::operator< (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint < b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint < b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong < b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong < b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong < b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong < b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt < b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl < b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl < b->m_data.ldbl; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + return a->m_integer.slt(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + return a->m_integer.ult(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) + return true; } return false; } @@ -2208,18 +2768,26 @@ lldb_private::operator<= (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint <= b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint <= b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong <= b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong <= b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong <= b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong <= b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt <= b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl <= b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl <= b->m_data.ldbl; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + return a->m_integer.sle(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + 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; } @@ -2234,18 +2802,26 @@ lldb_private::operator> (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint > b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint > b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong > b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong > b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong > b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong > b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt > b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl > b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl > b->m_data.ldbl; + case Scalar::e_void: break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + return a->m_integer.sgt(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + 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; } @@ -2259,22 +2835,140 @@ lldb_private::operator>= (const Scalar& lhs, const Scalar& rhs) 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: return a->m_data.sint >= b->m_data.sint; - case Scalar::e_uint: return a->m_data.uint >= b->m_data.uint; - case Scalar::e_slong: return a->m_data.slong >= b->m_data.slong; - case Scalar::e_ulong: return a->m_data.ulong >= b->m_data.ulong; - case Scalar::e_slonglong: return a->m_data.slonglong >= b->m_data.slonglong; - case Scalar::e_ulonglong: return a->m_data.ulonglong >= b->m_data.ulonglong; - case Scalar::e_float: return a->m_data.flt >= b->m_data.flt; - case Scalar::e_double: return a->m_data.dbl >= b->m_data.dbl; - case Scalar::e_long_double: return a->m_data.ldbl >= b->m_data.ldbl; + case Scalar::e_void: break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + return a->m_integer.sge(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + 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; } +bool +Scalar::ClearBit (uint32_t bit) +{ + switch (m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: m_integer.clearBit(bit); return true; + case e_float: + case e_double: + case e_long_double: break; + } + return false; +} +bool +Scalar::SetBit (uint32_t bit) +{ + switch (m_type) + { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: m_integer.setBit(bit); return true; + case e_float: + case e_double: + case e_long_double: break; + } + return false; +} - +void +Scalar::SetType (const RegisterInfo *reg_info) +{ + const uint32_t byte_size = reg_info->byte_size; + switch (reg_info->encoding) + { + case eEncodingInvalid: + break; + case eEncodingUint: + if (byte_size == 1 || byte_size == 2 || byte_size == 4) + { + m_integer = llvm::APInt(sizeof(uint_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + m_type = e_uint; + } + if (byte_size == 8) + { + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), false); + m_type = e_ulonglong; + } + if (byte_size == 16) + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())->x); + m_type = e_uint128; + } + break; + case eEncodingSint: + if (byte_size == 1 || byte_size == 2 || byte_size == 4) + { + m_integer = llvm::APInt(sizeof(sint_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + m_type = e_sint; + } + if (byte_size == 8) + { + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, *(const uint64_t *)m_integer.getRawData(), true); + m_type = e_slonglong; + } + if (byte_size == 16) + { + m_integer = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)m_integer.getRawData())->x); + m_type = e_sint128; + } + break; + case eEncodingIEEE754: + if (byte_size == sizeof(float)) + { + bool losesInfo = false; + m_float.convert(llvm::APFloat::IEEEsingle, llvm::APFloat::rmTowardZero, &losesInfo); + m_type = e_float; + } + else if (byte_size == sizeof(double)) + { + bool losesInfo = false; + m_float.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmTowardZero, &losesInfo); + m_type = e_double; + } + else if (byte_size == sizeof(long double)) + { + if(m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); + m_type = e_long_double; + } + break; + case eEncodingVector: + m_type = e_void; + break; + } +} diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index 9a3f220beb44..cf1cbac8fd7c 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -319,6 +319,25 @@ Section::Slide (addr_t slide_amount, bool slide_children) return false; } +lldb::offset_t +Section::GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset) +{ + if (m_obj_file) + return m_obj_file->ReadSectionData (this, + offset, + dst, + dst_len); + return 0; +} + +lldb::offset_t +Section::GetSectionData (DataExtractor& section_data) const +{ + if (m_obj_file) + return m_obj_file->ReadSectionData (this, section_data); + return 0; +} + #pragma mark SectionList SectionList::SectionList () : diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp index 324ed34bfaac..a69e75fe244a 100644 --- a/source/Core/SourceManager.cpp +++ b/source/Core/SourceManager.cpp @@ -18,7 +18,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" @@ -83,6 +82,10 @@ SourceManager::GetFile (const FileSpec &file_spec) if (target_sp && file_sp && file_sp->GetSourceMapModificationID() != target_sp->GetSourcePathMap().GetModificationID()) file_sp.reset(); + // Update the file contents if needed if we found a file + if (file_sp) + 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()) { @@ -492,8 +495,8 @@ SourceManager::File::LineIsValid (uint32_t line) return false; } -size_t -SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) +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. @@ -506,7 +509,11 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, m_data_sp = m_file_spec.ReadFileContents (); m_offsets.clear(); } +} +size_t +SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) +{ // Sanity check m_data_sp before proceeding. if (!m_data_sp) return 0; @@ -538,14 +545,6 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, void SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector &match_lines) { - TimeValue curr_mod_time (m_file_spec.GetModificationTime()); - if (m_mod_time != curr_mod_time) - { - m_mod_time = curr_mod_time; - m_data_sp = m_file_spec.ReadFileContents (); - m_offsets.clear(); - } - match_lines.clear(); if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) @@ -645,14 +644,14 @@ SourceManager::File::CalculateLineOffsets (uint32_t line) else { // Some lines have been populated, start where we last left off - assert("Not implemented yet" == NULL); + assert("Not implemented yet" && false); } } else { // Calculate all line offsets up to "line" - assert("Not implemented yet" == NULL); + assert("Not implemented yet" && false); } return false; } diff --git a/source/Core/Stream.cpp b/source/Core/Stream.cpp index 29bebb3ae3db..15876d558ec5 100644 --- a/source/Core/Stream.cpp +++ b/source/Core/Stream.cpp @@ -30,7 +30,7 @@ Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : Stream::Stream () : m_flags (0), m_addr_size (4), - m_byte_order (lldb::endian::InlHostByteOrder()), + m_byte_order (endian::InlHostByteOrder()), m_indent_level(0) { } @@ -284,9 +284,9 @@ Stream::operator<< (const char *s) // Stream the pointer value out to this stream. //------------------------------------------------------------------ Stream& -Stream::operator<< (void *p) +Stream::operator<< (const void *p) { - Printf ("0x%.*tx", (int)sizeof(void*) * 2, (ptrdiff_t)p); + Printf ("0x%.*tx", (int)sizeof(const void*) * 2, (ptrdiff_t)p); return *this; } @@ -632,7 +632,7 @@ Stream::PutMaxHex64 size_t Stream::PutPointer (void *ptr) { - return PutRawBytes (&ptr, sizeof(ptr), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); + return PutRawBytes (&ptr, sizeof(ptr), endian::InlHostByteOrder(), endian::InlHostByteOrder()); } size_t @@ -641,7 +641,7 @@ Stream::PutFloat(float f, ByteOrder byte_order) if (byte_order == eByteOrderInvalid) byte_order = m_byte_order; - return PutRawBytes (&f, sizeof(f), lldb::endian::InlHostByteOrder(), byte_order); + return PutRawBytes (&f, sizeof(f), endian::InlHostByteOrder(), byte_order); } size_t @@ -650,7 +650,7 @@ Stream::PutDouble(double d, ByteOrder byte_order) if (byte_order == eByteOrderInvalid) byte_order = m_byte_order; - return PutRawBytes (&d, sizeof(d), lldb::endian::InlHostByteOrder(), byte_order); + return PutRawBytes (&d, sizeof(d), endian::InlHostByteOrder(), byte_order); } size_t @@ -659,7 +659,7 @@ Stream::PutLongDouble(long double ld, ByteOrder byte_order) if (byte_order == eByteOrderInvalid) byte_order = m_byte_order; - return PutRawBytes (&ld, sizeof(ld), lldb::endian::InlHostByteOrder(), byte_order); + return PutRawBytes (&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order); } size_t @@ -743,21 +743,21 @@ Stream::UnitTest(Stream *s) s->PutHex8(0x12); s->PutChar(' '); - s->PutHex16(0x3456, lldb::endian::InlHostByteOrder()); + s->PutHex16(0x3456, endian::InlHostByteOrder()); s->PutChar(' '); s->PutHex16(0x3456, eByteOrderBig); s->PutChar(' '); s->PutHex16(0x3456, eByteOrderLittle); s->PutChar(' '); - s->PutHex32(0x789abcde, lldb::endian::InlHostByteOrder()); + s->PutHex32(0x789abcde, endian::InlHostByteOrder()); s->PutChar(' '); s->PutHex32(0x789abcde, eByteOrderBig); s->PutChar(' '); s->PutHex32(0x789abcde, eByteOrderLittle); s->PutChar(' '); - s->PutHex64(0x1122334455667788ull, lldb::endian::InlHostByteOrder()); + s->PutHex64(0x1122334455667788ull, endian::InlHostByteOrder()); s->PutChar(' '); s->PutHex64(0x1122334455667788ull, eByteOrderBig); s->PutChar(' '); diff --git a/source/Core/StreamAsynchronousIO.cpp b/source/Core/StreamAsynchronousIO.cpp index ccfde0c9a011..6f8fcce932e7 100644 --- a/source/Core/StreamAsynchronousIO.cpp +++ b/source/Core/StreamAsynchronousIO.cpp @@ -36,7 +36,7 @@ StreamAsynchronousIO::Flush () if (!m_data.empty()) { m_debugger.PrintAsync (m_data.data(), m_data.size(), m_for_stdout); - m_data = std::move(std::string()); + m_data = std::string(); } } diff --git a/source/Core/StreamString.cpp b/source/Core/StreamString.cpp index ef2b70583ebd..36e086b0b433 100644 --- a/source/Core/StreamString.cpp +++ b/source/Core/StreamString.cpp @@ -37,7 +37,7 @@ StreamString::Flush () size_t StreamString::Write (const void *s, size_t length) { - m_packet.append ((char *)s, length); + m_packet.append (reinterpret_cast(s), length); return length; } diff --git a/source/Core/Timer.cpp b/source/Core/Timer.cpp index bbd990056ba0..e53ce2ec453d 100644 --- a/source/Core/Timer.cpp +++ b/source/Core/Timer.cpp @@ -21,12 +21,27 @@ using namespace lldb_private; #define TIMER_INDENT_AMOUNT 2 -static bool g_quiet = true; -uint32_t Timer::g_depth = 0; -uint32_t Timer::g_display_depth = 0; -FILE * Timer::g_file = NULL; -typedef std::vector TimerStack; -typedef std::map TimerCategoryMap; + +namespace +{ + typedef std::map TimerCategoryMap; + + struct TimerStack + { + TimerStack() : + m_depth(0) + {} + + uint32_t m_depth; + std::vector m_stack; + }; +} // end of anonymous namespace + +std::atomic Timer::g_quiet(true); +std::atomic Timer::g_display_depth(0); +std::mutex Timer::g_file_mutex; +FILE* Timer::g_file = nullptr; + static lldb::thread_key_t g_key; static Mutex & @@ -82,12 +97,18 @@ Timer::Timer (const char *category, const char *format, ...) : m_total_ticks (0), m_timer_ticks (0) { - if (g_depth++ < g_display_depth) + TimerStack *stack = GetTimerStackForCurrentThread (); + if (!stack) + return; + + if (stack->m_depth++ < g_display_depth) { if (g_quiet == false) { + std::lock_guard lock(g_file_mutex); + // Indent - ::fprintf (g_file, "%*s", g_depth * TIMER_INDENT_AMOUNT, ""); + ::fprintf (g_file, "%*s", stack->m_depth * TIMER_INDENT_AMOUNT, ""); // Print formatted string va_list args; va_start (args, format); @@ -100,19 +121,19 @@ Timer::Timer (const char *category, const char *format, ...) : TimeValue start_time(TimeValue::Now()); m_total_start = start_time; m_timer_start = start_time; - TimerStack *stack = GetTimerStackForCurrentThread (); - if (stack) - { - if (stack->empty() == false) - stack->back()->ChildStarted (start_time); - stack->push_back(this); - } + + if (!stack->m_stack.empty()) + stack->m_stack.back()->ChildStarted (start_time); + stack->m_stack.push_back(this); } } - Timer::~Timer() { + TimerStack *stack = GetTimerStackForCurrentThread (); + if (!stack) + return; + if (m_total_start.IsValid()) { TimeValue stop_time = TimeValue::Now(); @@ -127,14 +148,10 @@ Timer::~Timer() m_timer_start.Clear(); } - TimerStack *stack = GetTimerStackForCurrentThread (); - if (stack) - { - assert (stack->back() == this); - stack->pop_back(); - if (stack->empty() == false) - stack->back()->ChildStopped(stop_time); - } + assert (stack->m_stack.back() == this); + stack->m_stack.pop_back(); + if (stack->m_stack.empty() == false) + stack->m_stack.back()->ChildStopped(stop_time); const uint64_t total_nsec_uint = GetTotalElapsedNanoSeconds(); const uint64_t timer_nsec_uint = GetTimerElapsedNanoSeconds(); @@ -143,10 +160,10 @@ Timer::~Timer() if (g_quiet == false) { - + std::lock_guard lock(g_file_mutex); ::fprintf (g_file, "%*s%.9f sec (%.9f sec)\n", - (g_depth - 1) *TIMER_INDENT_AMOUNT, "", + (stack->m_depth - 1) *TIMER_INDENT_AMOUNT, "", total_nsec / 1000000000.0, timer_nsec / 1000000000.0); } @@ -156,8 +173,8 @@ Timer::~Timer() TimerCategoryMap &category_map = GetCategoryMap(); category_map[m_category] += timer_nsec_uint; } - if (g_depth > 0) - --g_depth; + if (stack->m_depth > 0) + --stack->m_depth; } uint64_t diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp index a416d0745a69..a5c48e823ace 100644 --- a/source/Core/Value.cpp +++ b/source/Core/Value.cpp @@ -18,7 +18,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -35,7 +35,7 @@ using namespace lldb_private; Value::Value() : m_value (), m_vector (), - m_clang_type (), + m_compiler_type (), m_context (NULL), m_value_type (eValueTypeScalar), m_context_type (eContextTypeInvalid), @@ -46,7 +46,7 @@ Value::Value() : Value::Value(const Scalar& scalar) : m_value (scalar), m_vector (), - m_clang_type (), + m_compiler_type (), m_context (NULL), m_value_type (eValueTypeScalar), m_context_type (eContextTypeInvalid), @@ -58,7 +58,7 @@ Value::Value(const Scalar& scalar) : Value::Value(const void *bytes, int len) : m_value (), m_vector (), - m_clang_type (), + m_compiler_type (), m_context (NULL), m_value_type (eValueTypeHostAddress), m_context_type (eContextTypeInvalid), @@ -70,7 +70,7 @@ Value::Value(const void *bytes, int len) : Value::Value(const Value &v) : m_value (v.m_value), m_vector (v.m_vector), - m_clang_type (v.m_clang_type), + m_compiler_type (v.m_compiler_type), m_context (v.m_context), m_value_type (v.m_value_type), m_context_type (v.m_context_type), @@ -93,7 +93,7 @@ Value::operator=(const Value &rhs) { m_value = rhs.m_value; m_vector = rhs.m_vector; - m_clang_type = rhs.m_clang_type; + m_compiler_type = rhs.m_compiler_type; m_context = rhs.m_context; m_value_type = rhs.m_value_type; m_context_type = rhs.m_context_type; @@ -189,7 +189,7 @@ Value::AppendDataToHostBuffer (const Value &rhs) { rhs.m_value.GetAsMemoryData (m_data_buffer.GetBytes() + curr_size, scalar_size, - lldb::endian::InlHostByteOrder(), + endian::InlHostByteOrder(), error); return scalar_size; } @@ -260,7 +260,7 @@ Value::ValueOf(ExecutionContext *exe_ctx) } uint64_t -Value::GetValueByteSize (Error *error_ptr) +Value::GetValueByteSize (Error *error_ptr, ExecutionContext *exe_ctx) { uint64_t byte_size = 0; @@ -275,9 +275,9 @@ Value::GetValueByteSize (Error *error_ptr) case eContextTypeLLDBType: // Type * case eContextTypeVariable: // Variable * { - const ClangASTType &ast_type = GetClangType(); + const CompilerType &ast_type = GetCompilerType(); if (ast_type.IsValid()) - byte_size = ast_type.GetByteSize(nullptr); + byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); } break; } @@ -297,10 +297,10 @@ Value::GetValueByteSize (Error *error_ptr) return byte_size; } -const ClangASTType & -Value::GetClangType () +const CompilerType & +Value::GetCompilerType () { - if (!m_clang_type.IsValid()) + if (!m_compiler_type.IsValid()) { switch (m_context_type) { @@ -308,13 +308,13 @@ Value::GetClangType () break; case eContextTypeRegisterInfo: - break; // TODO: Eventually convert into a clang type? + break; // TODO: Eventually convert into a compiler type? case eContextTypeLLDBType: { Type *lldb_type = GetType(); if (lldb_type) - m_clang_type = lldb_type->GetClangForwardType(); + m_compiler_type = lldb_type->GetForwardCompilerType (); } break; @@ -325,20 +325,20 @@ Value::GetClangType () { Type *variable_type = variable->GetType(); if (variable_type) - m_clang_type = variable_type->GetClangForwardType(); + m_compiler_type = variable_type->GetForwardCompilerType (); } } break; } } - return m_clang_type; + return m_compiler_type; } void -Value::SetClangType (const ClangASTType &clang_type) +Value::SetCompilerType (const CompilerType &compiler_type) { - m_clang_type = clang_type; + m_compiler_type = compiler_type; } lldb::Format @@ -355,7 +355,7 @@ Value::GetValueDefaultFormat () case eContextTypeLLDBType: case eContextTypeVariable: { - const ClangASTType &ast_type = GetClangType(); + const CompilerType &ast_type = GetCompilerType(); if (ast_type.IsValid()) return ast_type.GetFormat(); } @@ -407,7 +407,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; Address file_so_addr; - const ClangASTType &ast_type = GetClangType(); + const CompilerType &ast_type = GetCompilerType(); switch (m_value_type) { case eValueTypeVector: @@ -420,7 +420,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, case eValueTypeScalar: { - data.SetByteOrder (lldb::endian::InlHostByteOrder()); + data.SetByteOrder (endian::InlHostByteOrder()); if (ast_type.IsValid()) data.SetAddressByteSize (ast_type.GetPointerByteSize()); else @@ -434,7 +434,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count); if (type_encoding == eEncodingUint || type_encoding == eEncodingSint) - limit_byte_size = ast_type.GetByteSize(nullptr); + limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); } if (m_value.GetData (data, limit_byte_size)) @@ -623,7 +623,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, } } // fallback to host settings - data.SetByteOrder(lldb::endian::InlHostByteOrder()); + data.SetByteOrder(endian::InlHostByteOrder()); data.SetAddressByteSize(sizeof(void *)); break; } @@ -639,7 +639,7 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, } // If we got here, we need to read the value from memory - size_t byte_size = GetValueByteSize (&error); + size_t byte_size = GetValueByteSize (&error, exe_ctx); // Bail if we encountered any errors getting the byte size if (error.Fail()) @@ -721,8 +721,8 @@ Value::GetValueAsData (ExecutionContext *exe_ctx, Scalar & Value::ResolveValue(ExecutionContext *exe_ctx) { - const ClangASTType &clang_type = GetClangType(); - if (clang_type.IsValid()) + const CompilerType &compiler_type = GetCompilerType(); + if (compiler_type.IsValid()) { switch (m_value_type) { @@ -740,7 +740,7 @@ Value::ResolveValue(ExecutionContext *exe_ctx) if (error.Success()) { Scalar scalar; - if (clang_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar)) + if (compiler_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar)) { m_value = scalar; m_value_type = eValueTypeScalar; @@ -782,7 +782,7 @@ Value::Clear() { m_value.Clear(); m_vector.Clear(); - m_clang_type.Clear(); + m_compiler_type.Clear(); m_value_type = eValueTypeScalar; m_context = NULL; m_context_type = eContextTypeInvalid; diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index 8718b37b95e0..6b1a6c590631 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -15,7 +15,6 @@ // C++ Includes // Other libraries and framework includes #include "llvm/Support/raw_ostream.h" -#include "clang/AST/Type.h" // Project includes #include "lldb/Core/DataBufferHeap.h" @@ -35,19 +34,20 @@ #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/Endian.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.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" @@ -97,6 +97,7 @@ ValueObject::ValueObject (ValueObject &parent) : m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid), m_value_checksum(), m_preferred_display_language(lldb::eLanguageTypeUnknown), + m_language_flags(0), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -148,6 +149,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope, m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), m_value_checksum(), m_preferred_display_language(lldb::eLanguageTypeUnknown), + m_language_flags(0), m_value_is_valid (false), m_value_did_change (false), m_children_count_valid (false), @@ -276,7 +278,7 @@ ValueObject::UpdateValueIfNeeded (bool update_format) bool ValueObject::UpdateFormatsIfNeeded() { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); if (log) log->Printf("[%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d", GetName().GetCString(), static_cast(this), @@ -316,39 +318,39 @@ ValueObject::ClearDynamicTypeInformation () m_children_count_valid = false; m_did_calculate_complete_objc_class_type = false; m_last_format_mgr_revision = 0; - m_override_type = ClangASTType(); + m_override_type = CompilerType(); SetValueFormat(lldb::TypeFormatImplSP()); SetSummaryFormat(lldb::TypeSummaryImplSP()); SetSyntheticChildren(lldb::SyntheticChildrenSP()); } -ClangASTType +CompilerType ValueObject::MaybeCalculateCompleteType () { - ClangASTType clang_type(GetClangTypeImpl()); + CompilerType compiler_type(GetCompilerTypeImpl()); if (m_did_calculate_complete_objc_class_type) { if (m_override_type.IsValid()) return m_override_type; else - return clang_type; + return compiler_type; } - ClangASTType class_type; + CompilerType class_type; bool is_pointer_type = false; - if (clang_type.IsObjCObjectPointerType(&class_type)) + if (ClangASTContext::IsObjCObjectPointerType(compiler_type, &class_type)) { is_pointer_type = true; } - else if (clang_type.IsObjCObjectOrInterfaceType()) + else if (ClangASTContext::IsObjCObjectOrInterfaceType(compiler_type)) { - class_type = clang_type; + class_type = compiler_type; } else { - return clang_type; + return compiler_type; } m_did_calculate_complete_objc_class_type = true; @@ -371,7 +373,7 @@ ValueObject::MaybeCalculateCompleteType () if (complete_objc_class_type_sp) { - ClangASTType complete_class(complete_objc_class_type_sp->GetClangFullType()); + CompilerType complete_class(complete_objc_class_type_sp->GetFullCompilerType ()); if (complete_class.GetCompleteType()) { @@ -392,11 +394,11 @@ ValueObject::MaybeCalculateCompleteType () } } } - return clang_type; + return compiler_type; } -ClangASTType -ValueObject::GetClangType () +CompilerType +ValueObject::GetCompilerType () { return MaybeCalculateCompleteType(); } @@ -404,7 +406,7 @@ ValueObject::GetClangType () TypeImpl ValueObject::GetTypeImpl () { - return TypeImpl(GetClangType()); + return TypeImpl(GetCompilerType()); } DataExtractor & @@ -513,6 +515,39 @@ ValueObject::ResolveValue (Scalar &scalar) return false; } +bool +ValueObject::IsLogicalTrue (Error& error) +{ + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) + { + LazyBool is_logical_true = language->IsLogicalTrue(*this, error); + switch (is_logical_true) + { + case eLazyBoolYes: + case eLazyBoolNo: + return (is_logical_true == true); + case eLazyBoolCalculate: + break; + } + } + + Scalar scalar_value; + + if (!ResolveValue (scalar_value)) + { + error.SetErrorString("failed to get a scalar result"); + return false; + } + + bool ret; + if (scalar_value.ULongLong(1) == 0) + ret = false; + else + ret = true; + error.Clear(); + return ret; +} + bool ValueObject::GetValueIsValid () const { @@ -566,40 +601,16 @@ ValueObjectSP ValueObject::GetChildAtIndexPath (const std::initializer_list& idxs, size_t* index_of_error) { - if (idxs.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (size_t idx : idxs) - { - root = root->GetChildAtIndex(idx, true); - if (!root) - { - if (index_of_error) - *index_of_error = idx; - return root; - } - } - return root; + return GetChildAtIndexPath( std::vector(idxs), + index_of_error ); } ValueObjectSP ValueObject::GetChildAtIndexPath (const std::initializer_list< std::pair >& idxs, size_t* index_of_error) { - if (idxs.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (std::pair idx : idxs) - { - root = root->GetChildAtIndex(idx.first, idx.second); - if (!root) - { - if (index_of_error) - *index_of_error = idx.first; - return root; - } - } - return root; + return GetChildAtIndexPath( std::vector>(idxs), + index_of_error ); } lldb::ValueObjectSP @@ -646,20 +657,16 @@ lldb::ValueObjectSP ValueObject::GetChildAtNamePath (const std::initializer_list &names, ConstString* name_of_error) { - if (names.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (ConstString name : names) - { - root = root->GetChildMemberWithName(name, true); - if (!root) - { - if (name_of_error) - *name_of_error = name; - return root; - } - } - return root; + return GetChildAtNamePath( std::vector(names), + name_of_error ); +} + +lldb::ValueObjectSP +ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair > &names, + ConstString* name_of_error) +{ + return GetChildAtNamePath( std::vector>(names), + name_of_error ); } lldb::ValueObjectSP @@ -683,7 +690,7 @@ ValueObject::GetChildAtNamePath (const std::vector &names, } lldb::ValueObjectSP -ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair > &names, +ValueObject::GetChildAtNamePath (const std::vector< std::pair > &names, ConstString* name_of_error) { if (names.size() == 0) @@ -696,37 +703,17 @@ ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair > &names, - ConstString* name_of_error) -{ - if (names.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (std::pair name : names) - { - root = root->GetChildMemberWithName(name.first, name.second); - if (!root) - { - if (name_of_error) - *name_of_error = name.first; - return root; - } - } - return root; -} - size_t ValueObject::GetIndexOfChildWithName (const ConstString &name) { bool omit_empty_base_classes = true; - return GetClangType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes); + return GetCompilerType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes); } ValueObjectSP @@ -743,7 +730,7 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) std::vector child_indexes; bool omit_empty_base_classes = true; - const size_t num_child_indexes = GetClangType().GetIndexOfChildMemberWithName (name.GetCString(), + const size_t num_child_indexes = GetCompilerType().GetIndexOfChildMemberWithName (name.GetCString(), omit_empty_base_classes, child_indexes); if (num_child_indexes > 0) @@ -771,9 +758,21 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) size_t -ValueObject::GetNumChildren () +ValueObject::GetNumChildren (uint32_t max) { UpdateValueIfNeeded(); + + if (max < UINT32_MAX) + { + if (m_children_count_valid) + { + size_t children_count = m_children.GetChildrenCount(); + return children_count <= max ? children_count : max; + } + else + return CalculateNumChildren(max); + } + if (!m_children_count_valid) { SetNumChildren (CalculateNumChildren()); @@ -828,26 +827,28 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_ uint32_t child_bitfield_bit_offset = 0; bool child_is_base_class = false; bool child_is_deref_of_parent = false; + uint64_t language_flags = 0; const bool transparent_pointers = synthetic_array_member == false; - ClangASTType child_clang_type; + CompilerType child_compiler_type; ExecutionContext exe_ctx (GetExecutionContextRef()); - child_clang_type = GetClangType().GetChildClangTypeAtIndex (&exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - 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, - this); - if (child_clang_type) + child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex (&exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + 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, + this, + language_flags); + if (child_compiler_type) { if (synthetic_index) child_byte_offset += child_byte_size * synthetic_index; @@ -857,7 +858,7 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_ child_name.SetCString (child_name_str.c_str()); valobj = new ValueObjectChild (*this, - child_clang_type, + child_compiler_type, child_name, child_byte_size, child_byte_offset, @@ -865,7 +866,8 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_ child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, - eAddressTypeInvalid); + eAddressTypeInvalid, + language_flags); //if (valobj) // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid); } @@ -875,9 +877,10 @@ ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_ bool ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, - std::string& destination) + std::string& destination, + lldb::LanguageType lang) { - return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions()); + return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions().SetLanguage(lang)); } bool @@ -886,7 +889,7 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, const TypeSummaryOptions& options) { destination.clear(); - + // ideally we would like to bail out if passing NULL, but if we do so // we end up not providing the summary for function pointers anymore if (/*summary_ptr == NULL ||*/ m_is_getting_summary) @@ -894,31 +897,38 @@ ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, m_is_getting_summary = true; + TypeSummaryOptions actual_options(options); + + if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown) + actual_options.SetLanguage(GetPreferredDisplayLanguage()); + // this is a hot path in code and we prefer to avoid setting this string all too often also clearing out other // information that we might care to see in a crash log. might be useful in very specific situations though. /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. Summary provider's description is %s", - GetTypeName().GetCString(), - GetName().GetCString(), - summary_ptr->GetDescription().c_str());*/ + GetTypeName().GetCString(), + GetName().GetCString(), + summary_ptr->GetDescription().c_str());*/ if (UpdateValueIfNeeded (false) && summary_ptr) { if (HasSyntheticValue()) m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#}) - summary_ptr->FormatObject(this, destination, options); + summary_ptr->FormatObject(this, destination, actual_options); } m_is_getting_summary = false; return !destination.empty(); } const char * -ValueObject::GetSummaryAsCString () +ValueObject::GetSummaryAsCString (lldb::LanguageType lang) { if (UpdateValueIfNeeded(true) && m_summary_str.empty()) { + TypeSummaryOptions summary_options; + summary_options.SetLanguage(lang); GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str, - TypeSummaryOptions()); + summary_options); } if (m_summary_str.empty()) return NULL; @@ -930,17 +940,17 @@ ValueObject::GetSummaryAsCString (std::string& destination, const TypeSummaryOptions& options) { return GetSummaryAsCString(GetSummaryFormat().get(), - destination, - options); + destination, + options); } bool ValueObject::IsCStringContainer(bool check_pointer) { - ClangASTType pointee_or_element_clang_type; - const Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type)); + CompilerType pointee_or_element_compiler_type; + const Flags type_flags (GetTypeInfo (&pointee_or_element_compiler_type)); bool is_char_arr_ptr (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && - pointee_or_element_clang_type.IsCharType ()); + pointee_or_element_compiler_type.IsCharType ()); if (!is_char_arr_ptr) return false; if (!check_pointer) @@ -958,8 +968,8 @@ ValueObject::GetPointeeData (DataExtractor& data, uint32_t item_idx, uint32_t item_count) { - ClangASTType pointee_or_element_clang_type; - const uint32_t type_info = GetTypeInfo (&pointee_or_element_clang_type); + CompilerType pointee_or_element_compiler_type; + const uint32_t type_info = GetTypeInfo (&pointee_or_element_compiler_type); const bool is_pointer_type = type_info & eTypeIsPointer; const bool is_array_type = type_info & eTypeIsArray; if (!(is_pointer_type || is_array_type)) @@ -970,7 +980,7 @@ ValueObject::GetPointeeData (DataExtractor& data, ExecutionContext exe_ctx (GetExecutionContextRef()); - const uint64_t item_type_size = pointee_or_element_clang_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); + 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; @@ -1046,12 +1056,12 @@ ValueObject::GetPointeeData (DataExtractor& data, break; case eAddressTypeHost: { - const uint64_t max_bytes = GetClangType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); + const uint64_t max_bytes = GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); if (max_bytes > offset) { size_t bytes_read = std::min(max_bytes - offset, bytes); addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (addr == LLDB_INVALID_ADDRESS) + if (addr == 0 || addr == LLDB_INVALID_ADDRESS) break; heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes_read); data.SetData(data_sp); @@ -1077,6 +1087,7 @@ ValueObject::GetData (DataExtractor& data, Error &error) if (m_data.GetByteSize()) { data = m_data; + error.Clear(); return data.GetByteSize(); } else @@ -1102,7 +1113,7 @@ ValueObject::SetData (DataExtractor &data, Error &error) } uint64_t count = 0; - const Encoding encoding = GetClangType().GetEncoding(count); + const Encoding encoding = GetCompilerType().GetEncoding(count); const size_t byte_size = GetByteSize(); @@ -1167,31 +1178,6 @@ ValueObject::SetData (DataExtractor &data, Error &error) return true; } -// will compute strlen(str), but without consuming more than -// maxlen bytes out of str (this serves the purpose of reading -// chunks of a string without having to worry about -// missing NULL terminators in the chunk) -// of course, if strlen(str) > maxlen, the function will return -// maxlen_value (which should be != maxlen, because that allows you -// to know whether strlen(str) == maxlen or strlen(str) > maxlen) -static uint32_t -strlen_or_inf (const char* str, - uint32_t maxlen, - uint32_t maxlen_value) -{ - uint32_t len = 0; - if (str) - { - while(*str) - { - len++;str++; - if (len >= maxlen) - return maxlen_value; - } - } - return len; -} - static bool CopyStringDataToBufferSP(const StreamString& source, lldb::DataBufferSP& destination) @@ -1201,13 +1187,14 @@ CopyStringDataToBufferSP(const StreamString& source, return true; } -size_t +std::pair ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, Error& error, uint32_t max_length, bool honor_array, Format item_format) { + bool was_capped = false; StreamString s; ExecutionContext exe_ctx (GetExecutionContextRef()); Target* target = exe_ctx.GetTargetPtr(); @@ -1217,7 +1204,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, s << ""; error.SetErrorString("no target to read from"); CopyStringDataToBufferSP(s, buffer_sp); - return 0; + return {0,was_capped}; } if (max_length == 0) @@ -1226,11 +1213,11 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, size_t bytes_read = 0; size_t total_bytes_read = 0; - ClangASTType clang_type = GetClangType(); - ClangASTType elem_or_pointee_clang_type; - const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type)); + CompilerType compiler_type = GetCompilerType(); + CompilerType elem_or_pointee_compiler_type; + const Flags type_flags (GetTypeInfo (&elem_or_pointee_compiler_type)); if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && - elem_or_pointee_clang_type.IsCharType ()) + elem_or_pointee_compiler_type.IsCharType ()) { addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; @@ -1241,7 +1228,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, { // We have an array uint64_t array_size = 0; - if (clang_type.IsArrayType(NULL, &array_size, NULL)) + if (compiler_type.IsArrayType(NULL, &array_size, NULL)) { cstr_len = array_size; if (cstr_len > max_length) @@ -1263,7 +1250,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, s << ""; error.SetErrorString("invalid address"); CopyStringDataToBufferSP(s, buffer_sp); - return 0; + return {0,was_capped}; } Address cstr_so_addr (cstr_address); @@ -1280,7 +1267,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, for (size_t offset = 0; offset < bytes_read; offset++) s.Printf("%c", *data.PeekData(offset, 1)); if (capped_data) - s << "..."; + was_capped = true; } } else @@ -1298,10 +1285,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, { total_bytes_read += bytes_read; const char *cstr = data.PeekCStr(0); - size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1); - if (len > k_max_buf_size) - len = k_max_buf_size; - + size_t len = strnlen (cstr, k_max_buf_size); if (cstr_len_displayed < 0) cstr_len_displayed = len; @@ -1332,7 +1316,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, if (cstr_len_displayed >= 0) { if (capped_cstr) - s << "..."; + was_capped = true; } } } @@ -1342,7 +1326,7 @@ ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, s << ""; } CopyStringDataToBufferSP(s, buffer_sp); - return total_bytes_read; + return {total_bytes_read,was_capped}; } std::pair @@ -1385,11 +1369,11 @@ ValueObject::GetObjectDescription () if (runtime == NULL) { // Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway... - ClangASTType clang_type = GetClangType(); - if (clang_type) + CompilerType compiler_type = GetCompilerType(); + if (compiler_type) { bool is_signed; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType ()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType ()) { runtime = process->GetLanguageRuntime(eLanguageTypeObjC); } @@ -1449,7 +1433,7 @@ ValueObject::GetValueAsCString () } else { - my_format = GetValue().GetClangType().GetFormat(); + my_format = GetValue().GetCompilerType().GetFormat(); } } } @@ -1590,18 +1574,19 @@ ValueObject::DumpPrintableRepresentation(Stream& s, { Error error; lldb::DataBufferSP buffer_sp; - ReadPointedString(buffer_sp, - error, - 0, - (custom_format == eFormatVectorOfChar) || - (custom_format == eFormatCharArray)); - lldb_private::formatters::ReadBufferAndDumpToStreamOptions options(*this); + std::pair read_string = ReadPointedString(buffer_sp, + error, + 0, + (custom_format == eFormatVectorOfChar) || + (custom_format == eFormatCharArray)); + lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions options(*this); options.SetData(DataExtractor(buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults options.SetStream(&s); options.SetPrefixToken(0); options.SetQuote('"'); options.SetSourceSize(buffer_sp->GetByteSize()); - lldb_private::formatters::ReadBufferAndDumpToStream(options); + options.SetIsTruncated(read_string.second); + formatters::StringPrinter::ReadBufferAndDumpToStream(options); return !error.Fail(); } @@ -1886,7 +1871,7 @@ ValueObject::SetValueFromCString (const char *value_str, Error& error) } uint64_t count = 0; - const Encoding encoding = GetClangType().GetEncoding (count); + const Encoding encoding = GetCompilerType().GetEncoding (count); const size_t byte_size = GetByteSize(); @@ -1897,7 +1882,7 @@ ValueObject::SetValueFromCString (const char *value_str, Error& error) // If the value is already a scalar, then let the scalar change itself: m_value.GetScalar().SetValueFromCString (value_str, encoding, byte_size); } - else if (byte_size <= Scalar::GetMaxByteSize()) + else if (byte_size <= 16) { // If the value fits in a scalar, then make a new scalar and again let the // scalar code do the conversion, then figure out where to put the new value. @@ -1984,7 +1969,7 @@ ValueObject::GetDeclaration (Declaration &decl) ConstString ValueObject::GetTypeName() { - return GetClangType().GetConstTypeName(); + return GetCompilerType().GetConstTypeName(); } ConstString @@ -1996,14 +1981,14 @@ ValueObject::GetDisplayTypeName() ConstString ValueObject::GetQualifiedTypeName() { - return GetClangType().GetConstQualifiedTypeName(); + return GetCompilerType().GetConstQualifiedTypeName(); } LanguageType ValueObject::GetObjectRuntimeLanguage () { - return GetClangType().GetMinimumLanguage (); + return GetCompilerType().GetMinimumLanguage (); } void @@ -2023,39 +2008,39 @@ ValueObject::GetSyntheticChild (const ConstString &key) const } uint32_t -ValueObject::GetTypeInfo (ClangASTType *pointee_or_element_clang_type) +ValueObject::GetTypeInfo (CompilerType *pointee_or_element_compiler_type) { - return GetClangType().GetTypeInfo (pointee_or_element_clang_type); + return GetCompilerType().GetTypeInfo (pointee_or_element_compiler_type); } bool ValueObject::IsPointerType () { - return GetClangType().IsPointerType(); + return GetCompilerType().IsPointerType(); } bool ValueObject::IsArrayType () { - return GetClangType().IsArrayType (NULL, NULL, NULL); + return GetCompilerType().IsArrayType (NULL, NULL, NULL); } bool ValueObject::IsScalarType () { - return GetClangType().IsScalarType (); + return GetCompilerType().IsScalarType (); } bool ValueObject::IsIntegerType (bool &is_signed) { - return GetClangType().IsIntegerType (is_signed); + return GetCompilerType().IsIntegerType (is_signed); } bool ValueObject::IsPointerOrReferenceType () { - return GetClangType().IsPointerOrReferenceType (); + return GetCompilerType().IsPointerOrReferenceType (); } bool @@ -2066,7 +2051,7 @@ ValueObject::IsPossibleDynamicType () if (process) return process->IsPossibleDynamicValue(*this); else - return GetClangType().IsPossibleDynamicType (NULL, true, true); + return GetCompilerType().IsPossibleDynamicType (NULL, true, true); } bool @@ -2085,15 +2070,23 @@ ValueObject::IsRuntimeSupportValue () } bool -ValueObject::IsObjCNil () +ValueObject::IsNilReference () { - const uint32_t mask = eTypeIsObjC | eTypeIsPointer; - bool isObjCpointer = (((GetClangType().GetTypeInfo(NULL)) & mask) == mask); - if (!isObjCpointer) - return false; - bool canReadValue = true; - bool isZero = GetValueAsUnsigned(0,&canReadValue) == 0; - return canReadValue && isZero; + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) + { + return language->IsNilReference(*this); + } + return false; +} + +bool +ValueObject::IsUninitializedReference () +{ + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) + { + return language->IsUninitializedReference(*this); + } + return false; } // This allows you to create an array member using and index @@ -2156,7 +2149,7 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre // We haven't made a synthetic array member for INDEX yet, so // lets make one and cache it for any future reference. ValueObjectChild *synthetic_child = new ValueObjectChild (*this, - GetClangType(), + GetCompilerType(), index_const_str, GetByteSize(), 0, @@ -2164,7 +2157,8 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre from, false, false, - eAddressTypeInvalid); + eAddressTypeInvalid, + 0); // Cache the value if we got one back... if (synthetic_child) @@ -2180,7 +2174,7 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre } ValueObjectSP -ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) { ValueObjectSP synthetic_child_sp; @@ -2210,7 +2204,8 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type 0, false, false, - eAddressTypeInvalid); + eAddressTypeInvalid, + 0); if (synthetic_child) { AddSyntheticChild(name_const_str, synthetic_child); @@ -2222,7 +2217,7 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type } ValueObjectSP -ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool can_create) +ValueObject::GetSyntheticBase (uint32_t offset, const CompilerType& type, bool can_create) { ValueObjectSP synthetic_child_sp; @@ -2253,7 +2248,8 @@ ValueObject::GetSyntheticBase (uint32_t offset, const ClangASTType& type, bool c 0, is_base_class, false, - eAddressTypeInvalid); + eAddressTypeInvalid, + 0); if (synthetic_child) { AddSyntheticChild(name_const_str, synthetic_child); @@ -2417,9 +2413,9 @@ ValueObject::GetBaseClassPath (Stream &s) if (IsBaseClass()) { bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s); - ClangASTType clang_type = GetClangType(); + CompilerType compiler_type = GetCompilerType(); std::string cxx_class_name; - bool this_had_base_class = clang_type.GetCXXClassName (cxx_class_name); + bool this_had_base_class = ClangASTContext::GetCXXClassName (compiler_type, cxx_class_name); if (this_had_base_class) { if (parent_had_base_class) @@ -2536,8 +2532,8 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp ValueObject *non_base_class_parent = GetNonBaseClassParent(); if (non_base_class_parent) { - ClangASTType non_base_class_parent_clang_type = non_base_class_parent->GetClangType(); - if (non_base_class_parent_clang_type) + CompilerType non_base_class_parent_compiler_type = non_base_class_parent->GetCompilerType(); + if (non_base_class_parent_compiler_type) { if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers) { @@ -2545,7 +2541,7 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExp } else { - const uint32_t non_base_class_parent_type_info = non_base_class_parent_clang_type.GetTypeInfo(); + const uint32_t non_base_class_parent_type_info = non_base_class_parent_compiler_type.GetTypeInfo(); if (non_base_class_parent_type_info & eTypeIsPointer) { @@ -2757,13 +2753,13 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr - ClangASTType root_clang_type = root->GetClangType(); - ClangASTType pointee_clang_type; - Flags pointee_clang_type_info; + CompilerType root_compiler_type = root->GetCompilerType(); + CompilerType pointee_compiler_type; + Flags pointee_compiler_type_info; - Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type)); - if (pointee_clang_type) - pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo()); + Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type)); + if (pointee_compiler_type) + pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); if (!expression_cstr || *expression_cstr == '\0') { @@ -2776,15 +2772,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '-': { if (options.m_check_dot_vs_arrow_syntax && - root_clang_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error + root_compiler_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; return ValueObjectSP(); } - if (root_clang_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden - root_clang_type_info.Test(eTypeIsPointer) && + if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden + root_compiler_type_info.Test(eTypeIsPointer) && options.m_no_fragile_ivar) { *first_unparsed = expression_cstr; @@ -2804,7 +2800,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '.': // or fallthrough from -> { if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && - root_clang_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error + root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; @@ -2953,9 +2949,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } case '[': { - if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer) && !root_clang_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T* + if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer) && !root_compiler_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T* { - if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar... + if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar... { if (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None) // ...only chance left is synthetic { @@ -2975,7 +2971,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!root_clang_type_info.Test(eTypeIsArray)) + if (!root_compiler_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; @@ -3012,7 +3008,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (root_clang_type_info.Test(eTypeIsArray)) + if (root_compiler_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr+2; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; @@ -3028,7 +3024,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } // from here on we do have a valid index - if (root_clang_type_info.Test(eTypeIsArray)) + if (root_compiler_type_info.Test(eTypeIsArray)) { ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); if (!child_valobj_sp) @@ -3051,10 +3047,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return ValueObjectSP(); } } - else if (root_clang_type_info.Test(eTypeIsPointer)) + else if (root_compiler_type_info.Test(eTypeIsPointer)) { if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_clang_type_info.Test(eTypeIsScalar)) + pointee_compiler_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3073,8 +3069,8 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } else { - if (root->GetClangType().GetMinimumLanguage() == eLanguageTypeObjC - && pointee_clang_type_info.AllClear(eTypeIsPointer) + if (root->GetCompilerType().GetMinimumLanguage() == eLanguageTypeObjC + && pointee_compiler_type_info.AllClear(eTypeIsPointer) && root->HasSyntheticValue() && (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic || options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both)) @@ -3098,7 +3094,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } } - else if (root_clang_type_info.Test(eTypeIsScalar)) + else if (root_compiler_type_info.Test(eTypeIsScalar)) { root = root->GetSyntheticBitFieldChild(index, index, true); if (!root.get()) @@ -3116,7 +3112,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (root_clang_type_info.Test(eTypeIsVector)) + else if (root_compiler_type_info.Test(eTypeIsVector)) { root = root->GetChildAtIndex(index, true); if (!root.get()) @@ -3202,7 +3198,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, index_lower = index_higher; index_higher = temp; } - if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars + if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -3220,9 +3216,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_clang_type_info.Test(eTypeIsScalar)) + pointee_compiler_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3281,12 +3277,12 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr - ClangASTType root_clang_type = root->GetClangType(); - ClangASTType pointee_clang_type; - Flags pointee_clang_type_info; - Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type)); - if (pointee_clang_type) - pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo()); + CompilerType root_compiler_type = root->GetCompilerType(); + CompilerType pointee_compiler_type; + Flags pointee_compiler_type_info; + Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type)); + if (pointee_compiler_type) + pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); if (!expression_cstr || *expression_cstr == '\0') { @@ -3299,9 +3295,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, { case '[': { - if (!root_clang_type_info.Test(eTypeIsArray) && !root_clang_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T* + if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T* { - if (!root_clang_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! + if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; @@ -3318,7 +3314,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!root_clang_type_info.Test(eTypeIsArray)) + if (!root_compiler_type_info.Test(eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; @@ -3362,7 +3358,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (root_clang_type_info.Test(eTypeIsArray)) + if (root_compiler_type_info.Test(eTypeIsArray)) { const size_t max_index = root->GetNumChildren() - 1; for (size_t index = 0; index < max_index; index++) @@ -3385,7 +3381,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } } // from here on we do have a valid index - if (root_clang_type_info.Test(eTypeIsArray)) + if (root_compiler_type_info.Test(eTypeIsArray)) { root = root->GetChildAtIndex(index, true); if (!root.get()) @@ -3404,10 +3400,10 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, return 1; } } - else if (root_clang_type_info.Test(eTypeIsPointer)) + else if (root_compiler_type_info.Test(eTypeIsPointer)) { if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_clang_type_info.Test(eTypeIsScalar)) + pointee_compiler_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3444,7 +3440,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } } } - else /*if (ClangASTContext::IsScalarType(root_clang_type))*/ + else /*if (ClangASTContext::IsScalarType(root_compiler_type))*/ { root = root->GetSyntheticBitFieldChild(index, index, true); if (!root.get()) @@ -3489,7 +3485,7 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, index_lower = index_higher; index_higher = temp; } - if (root_clang_type_info.Test(eTypeIsScalar)) // expansion only works for scalars + if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -3508,9 +3504,9 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, return 1; } } - else if (root_clang_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_clang_type_info.Test(eTypeIsScalar)) + pointee_compiler_type_info.Test(eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -3611,7 +3607,7 @@ ValueObject::CreateConstantValue (const ConstString &name) m_error = m_value.GetValueAsData (&exe_ctx, data, 0, GetModule().get()); valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - GetClangType(), + GetCompilerType(), name, data, GetAddressOf()); @@ -3677,8 +3673,8 @@ ValueObject::GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynVa lldb::addr_t ValueObject::GetCPPVTableAddress (AddressType &address_type) { - ClangASTType pointee_type; - ClangASTType this_type(GetClangType()); + CompilerType pointee_type; + CompilerType this_type(GetCompilerType()); uint32_t type_info = this_type.GetTypeInfo(&pointee_type); if (type_info) { @@ -3711,9 +3707,9 @@ ValueObject::Dereference (Error &error) { if (m_deref_valobj) return m_deref_valobj->GetSP(); - - const bool is_pointer_type = IsPointerType(); - if (is_pointer_type) + + const bool is_pointer_or_reference_type = IsPointerOrReferenceType(); + if (is_pointer_or_reference_type) { bool omit_empty_base_classes = true; bool ignore_array_bounds = false; @@ -3726,32 +3722,34 @@ ValueObject::Dereference (Error &error) bool child_is_base_class = false; bool child_is_deref_of_parent = false; const bool transparent_pointers = false; - ClangASTType clang_type = GetClangType(); - ClangASTType child_clang_type; + CompilerType compiler_type = GetCompilerType(); + CompilerType child_compiler_type; + uint64_t language_flags; ExecutionContext exe_ctx (GetExecutionContextRef()); - - child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx, - 0, - transparent_pointers, - omit_empty_base_classes, - 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, - this); - if (child_clang_type && child_byte_size) + + child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx, + 0, + transparent_pointers, + omit_empty_base_classes, + 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, + this, + language_flags); + if (child_compiler_type && child_byte_size) { ConstString child_name; if (!child_name_str.empty()) child_name.SetCString (child_name_str.c_str()); m_deref_valobj = new ValueObjectChild (*this, - child_clang_type, + child_compiler_type, child_name, child_byte_size, child_byte_offset, @@ -3759,7 +3757,8 @@ ValueObject::Dereference (Error &error) child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, - eAddressTypeInvalid); + eAddressTypeInvalid, + language_flags); } } @@ -3773,10 +3772,10 @@ ValueObject::Dereference (Error &error) StreamString strm; GetExpressionPath(strm, true); - if (is_pointer_type) + if (is_pointer_or_reference_type) error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString(""), strm.GetString().c_str()); else - error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString(""), strm.GetString().c_str()); + error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s", GetTypeName().AsCString(""), strm.GetString().c_str()); return ValueObjectSP(); } } @@ -3806,14 +3805,14 @@ ValueObject::AddressOf (Error &error) case eAddressTypeFile: case eAddressTypeLoad: { - ClangASTType clang_type = GetClangType(); - if (clang_type) + CompilerType compiler_type = GetCompilerType(); + if (compiler_type) { std::string name (1, '&'); name.append (m_name.AsCString("")); ExecutionContext exe_ctx (GetExecutionContextRef()); m_addr_of_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - clang_type.GetPointerType(), + compiler_type.GetPointerType(), ConstString (name.c_str()), addr, eAddressTypeInvalid, @@ -3836,13 +3835,13 @@ ValueObject::AddressOf (Error &error) } ValueObjectSP -ValueObject::Cast (const ClangASTType &clang_ast_type) +ValueObject::Cast (const CompilerType &compiler_type) { - return ValueObjectCast::Create (*this, GetName(), clang_ast_type); + return ValueObjectCast::Create (*this, GetName(), compiler_type); } ValueObjectSP -ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type) +ValueObject::CastPointerType (const char *name, CompilerType &compiler_type) { ValueObjectSP valobj_sp; AddressType address_type; @@ -3855,7 +3854,7 @@ ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type) valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, - clang_ast_type); + compiler_type); } return valobj_sp; } @@ -4104,11 +4103,11 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress (const char* name, uint64_t address, const ExecutionContext& exe_ctx, - ClangASTType type) + CompilerType type) { if (type) { - ClangASTType pointer_type(type.GetPointerType()); + CompilerType pointer_type(type.GetPointerType()); if (pointer_type) { lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); @@ -4136,7 +4135,7 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromData (const char* name, const DataExtractor& data, const ExecutionContext& exe_ctx, - ClangASTType type) + CompilerType type) { lldb::ValueObjectSP new_value_sp; new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), @@ -4252,13 +4251,20 @@ ValueObject::SetPreferredDisplayLanguage (lldb::LanguageType lt) m_preferred_display_language = lt; } +void +ValueObject::SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType lt) +{ + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) + SetPreferredDisplayLanguage(lt); +} + bool ValueObject::CanProvideValue () { // we need to support invalid types as providers of values because some bare-board // debugging scenarios have no notion of types, but still manage to have raw numeric // values for things like registers. sigh. - const ClangASTType &type(GetClangType()); + const CompilerType &type(GetCompilerType()); return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue)); } @@ -4278,15 +4284,18 @@ ValueObject::Persist () if (!target_sp) return nullptr; - ConstString name(target_sp->GetPersistentVariables().GetNextPersistentVariableName()); + PersistentExpressionState *persistent_state = target_sp->GetPersistentExpressionStateForLanguage(GetPreferredDisplayLanguage()); - ClangExpressionVariableSP clang_var_sp(new ClangExpressionVariable(target_sp.get(), GetValue(), name)); - if (clang_var_sp) - { - clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp; - clang_var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference; - target_sp->GetPersistentVariables().AddVariable(clang_var_sp); - } + if (!persistent_state) + return nullptr; + + ConstString name(persistent_state->GetNextPersistentVariableName()); + + ValueObjectSP const_result_sp = ValueObjectConstResult::Create (target_sp.get(), GetValue(), name); + + ExpressionVariableSP clang_var_sp = persistent_state->CreatePersistentVariable(const_result_sp); + clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp; + clang_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference; return clang_var_sp->GetValueObject(); } @@ -4302,3 +4311,15 @@ ValueObject::SetSyntheticChildrenGenerated (bool b) { m_is_synthetic_children_generated = b; } + +uint64_t +ValueObject::GetLanguageFlags () +{ + return m_language_flags; +} + +void +ValueObject::SetLanguageFlags (uint64_t flags) +{ + m_language_flags = flags; +} diff --git a/source/Core/ValueObjectCast.cpp b/source/Core/ValueObjectCast.cpp index b20371b128df..1c5838b820e1 100644 --- a/source/Core/ValueObjectCast.cpp +++ b/source/Core/ValueObjectCast.cpp @@ -20,14 +20,13 @@ #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -38,7 +37,7 @@ using namespace lldb_private; lldb::ValueObjectSP ValueObjectCast::Create (ValueObject &parent, const ConstString &name, - const ClangASTType &cast_type) + const CompilerType &cast_type) { ValueObjectCast *cast_valobj_ptr = new ValueObjectCast (parent, name, cast_type); return cast_valobj_ptr->GetSP(); @@ -48,36 +47,38 @@ ValueObjectCast::ValueObjectCast ( ValueObject &parent, const ConstString &name, - const ClangASTType &cast_type + const CompilerType &cast_type ) : ValueObject(parent), m_cast_type (cast_type) { SetName (name); //m_value.SetContext (Value::eContextTypeClangType, cast_type.GetOpaqueQualType()); - m_value.SetClangType (cast_type); + m_value.SetCompilerType (cast_type); } ValueObjectCast::~ValueObjectCast() { } -ClangASTType -ValueObjectCast::GetClangTypeImpl () +CompilerType +ValueObjectCast::GetCompilerTypeImpl () { return m_cast_type; } size_t -ValueObjectCast::CalculateNumChildren() +ValueObjectCast::CalculateNumChildren(uint32_t max) { - return GetClangType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } uint64_t ValueObjectCast::GetByteSize() { - return m_value.GetValueByteSize(NULL); + ExecutionContext exe_ctx (GetExecutionContextRef()); + return m_value.GetValueByteSize(nullptr, &exe_ctx); } lldb::ValueType @@ -98,9 +99,9 @@ ValueObjectCast::UpdateValue () Value old_value(m_value); m_update_point.SetUpdated(); m_value = m_parent->GetValue(); - ClangASTType clang_type (GetClangType()); - //m_value.SetContext (Value::eContextTypeClangType, clang_type); - m_value.SetClangType (clang_type); + CompilerType compiler_type (GetCompilerType()); + //m_value.SetContext (Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType (compiler_type); SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); if (!CanProvideValue()) { diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp index c1e45e1f48de..6ecc749b8953 100644 --- a/source/Core/ValueObjectChild.cpp +++ b/source/Core/ValueObjectChild.cpp @@ -12,7 +12,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -27,7 +27,7 @@ using namespace lldb_private; ValueObjectChild::ValueObjectChild ( ValueObject &parent, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, uint64_t byte_size, int32_t byte_offset, @@ -35,19 +35,22 @@ ValueObjectChild::ValueObjectChild uint32_t bitfield_bit_offset, bool is_base_class, bool is_deref_of_parent, - AddressType child_ptr_or_ref_addr_type + AddressType child_ptr_or_ref_addr_type, + uint64_t language_flags ) : ValueObject (parent), - m_clang_type (clang_type), + m_compiler_type (compiler_type), m_byte_size (byte_size), m_byte_offset (byte_offset), m_bitfield_bit_size (bitfield_bit_size), m_bitfield_bit_offset (bitfield_bit_offset), m_is_base_class (is_base_class), - m_is_deref_of_parent (is_deref_of_parent) + m_is_deref_of_parent (is_deref_of_parent), + m_can_update_with_invalid_exe_ctx() { m_name = name; SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); + SetLanguageFlags(language_flags); } ValueObjectChild::~ValueObjectChild() @@ -61,9 +64,10 @@ ValueObjectChild::GetValueType() const } size_t -ValueObjectChild::CalculateNumChildren() +ValueObjectChild::CalculateNumChildren(uint32_t max) { - return GetClangType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } static void @@ -72,11 +76,11 @@ AdjustForBitfieldness(ConstString& name, { if (name && bitfield_bit_size) { - const char *clang_type_name = name.AsCString(); - if (clang_type_name) + const char *compiler_type_name = name.AsCString(); + if (compiler_type_name) { - std::vector bitfield_type_name (strlen(clang_type_name) + 32, 0); - ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, bitfield_bit_size); + std::vector bitfield_type_name (strlen(compiler_type_name) + 32, 0); + ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", compiler_type_name, bitfield_bit_size); name.SetCString(&bitfield_type_name.front()); } } @@ -87,7 +91,7 @@ ValueObjectChild::GetTypeName() { if (m_type_name.IsEmpty()) { - m_type_name = GetClangType().GetConstTypeName (); + m_type_name = GetCompilerType().GetConstTypeName (); AdjustForBitfieldness(m_type_name, m_bitfield_bit_size); } return m_type_name; @@ -96,7 +100,7 @@ ValueObjectChild::GetTypeName() ConstString ValueObjectChild::GetQualifiedTypeName() { - ConstString qualified_name = GetClangType().GetConstTypeName(); + ConstString qualified_name = GetCompilerType().GetConstTypeName(); AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); return qualified_name; } @@ -104,17 +108,25 @@ ValueObjectChild::GetQualifiedTypeName() ConstString ValueObjectChild::GetDisplayTypeName() { - ConstString display_name = GetClangType().GetDisplayTypeName(); + ConstString display_name = GetCompilerType().GetDisplayTypeName(); AdjustForBitfieldness(display_name, m_bitfield_bit_size); return display_name; } -bool +LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext () { + if (m_can_update_with_invalid_exe_ctx.hasValue()) + return m_can_update_with_invalid_exe_ctx.getValue(); if (m_parent) - return m_parent->CanUpdateWithInvalidExecutionContext(); - return this->ValueObject::CanUpdateWithInvalidExecutionContext(); + { + ValueObject *opinionated_parent = m_parent->FollowParentChain([] (ValueObject* valobj) -> bool { + return (valobj->CanUpdateWithInvalidExecutionContext() == eLazyBoolCalculate); + }); + if (opinionated_parent) + return (m_can_update_with_invalid_exe_ctx = opinionated_parent->CanUpdateWithInvalidExecutionContext()).getValue(); + } + return (m_can_update_with_invalid_exe_ctx = this->ValueObject::CanUpdateWithInvalidExecutionContext()).getValue(); } bool @@ -127,18 +139,22 @@ ValueObjectChild::UpdateValue () { if (parent->UpdateValueIfNeeded(false)) { - m_value.SetClangType(GetClangType()); - + m_value.SetCompilerType(GetCompilerType()); + + CompilerType parent_type(parent->GetCompilerType()); // Copy the parent scalar value and the scalar value type m_value.GetScalar() = parent->GetValue().GetScalar(); Value::ValueType value_type = parent->GetValue().GetValueType(); m_value.SetValueType (value_type); + + Flags parent_type_flags(parent_type.GetTypeInfo()); + const bool is_instance_ptr_base = ((m_is_base_class == true) && (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer))); - if (parent->GetClangType().IsPointerOrReferenceType ()) + if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) { lldb::addr_t addr = parent->GetPointerValue (); m_value.GetScalar() = addr; - + if (addr == LLDB_INVALID_ADDRESS) { m_error.SetErrorString ("parent address is invalid."); @@ -155,16 +171,16 @@ ValueObjectChild::UpdateValue () switch (addr_type) { case eAddressTypeFile: - { - lldb::ProcessSP process_sp (GetProcessSP()); - if (process_sp && process_sp->IsAlive() == true) - m_value.SetValueType (Value::eValueTypeLoadAddress); - else - m_value.SetValueType(Value::eValueTypeFileAddress); - } + { + lldb::ProcessSP process_sp (GetProcessSP()); + if (process_sp && process_sp->IsAlive() == true) + m_value.SetValueType (Value::eValueTypeLoadAddress); + else + m_value.SetValueType(Value::eValueTypeFileAddress); + } break; case eAddressTypeLoad: - m_value.SetValueType (Value::eValueTypeLoadAddress); + m_value.SetValueType (is_instance_ptr_base ? Value::eValueTypeScalar: Value::eValueTypeLoadAddress); break; case eAddressTypeHost: m_value.SetValueType(Value::eValueTypeHostAddress); @@ -180,9 +196,9 @@ ValueObjectChild::UpdateValue () { switch (value_type) { - case Value::eValueTypeLoadAddress: - case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeFileAddress: + case Value::eValueTypeHostAddress: { lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); if (addr == LLDB_INVALID_ADDRESS) @@ -200,27 +216,42 @@ ValueObjectChild::UpdateValue () m_value.GetScalar() += GetByteOffset(); } } - break; - - case Value::eValueTypeScalar: - // TODO: What if this is a register value? Do we try and - // extract the child value from within the parent data? - // Probably... - default: - m_error.SetErrorString ("parent has invalid value."); - break; + break; + + case Value::eValueTypeScalar: + // try to extract the child value from the parent's scalar value + { + Scalar scalar(m_value.GetScalar()); + if (m_bitfield_bit_size) + scalar.ExtractBitfield(m_bitfield_bit_size, m_bitfield_bit_offset); + else + scalar.ExtractBitfield(8*m_byte_size, 8*m_byte_offset); + m_value.GetScalar() = scalar; + } + break; + default: + m_error.SetErrorString ("parent has invalid value."); + break; } } - + if (m_error.Success()) { const bool thread_and_frame_only_if_stopped = true; ExecutionContext exe_ctx (GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); - if (GetClangType().GetTypeInfo() & lldb::eTypeHasValue) - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); + 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()); + } else + { m_error.Clear(); // No value so nothing to read... + } } + } else { diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp index b4e630306469..a0f1737a861c 100644 --- a/source/Core/ValueObjectConstResult.cpp +++ b/source/Core/ValueObjectConstResult.cpp @@ -16,7 +16,7 @@ #include "lldb/Core/ValueObjectDynamicValue.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -61,21 +61,21 @@ ValueObjectSP ValueObjectConstResult::Create ( ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const DataExtractor &data, lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, - clang_type, + compiler_type, name, data, address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const DataExtractor &data, lldb::addr_t address) : @@ -94,7 +94,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); m_value.SetValueType(Value::eValueTypeHostAddress); - m_value.SetClangType(clang_type); + m_value.SetCompilerType(compiler_type); m_name = name; SetIsConstant (); SetValueIsValid(true); @@ -103,7 +103,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope ValueObjectSP ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, @@ -111,7 +111,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, lldb::addr_t address) { return (new ValueObjectConstResult (exe_scope, - clang_type, + compiler_type, name, data_sp, data_byte_order, @@ -129,7 +129,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, } ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, @@ -145,8 +145,8 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope m_data.SetData(data_sp); m_value.GetScalar() = (uintptr_t)data_sp->GetBytes(); m_value.SetValueType(Value::eValueTypeHostAddress); - //m_value.SetContext(Value::eContextTypeClangType, clang_type); - m_value.SetClangType (clang_type); + //m_value.SetContext(Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType (compiler_type); m_name = name; SetIsConstant (); SetValueIsValid(true); @@ -155,14 +155,14 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope ValueObjectSP ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, lldb::addr_t address, AddressType address_type, uint32_t addr_byte_size) { return (new ValueObjectConstResult (exe_scope, - clang_type, + compiler_type, name, address, address_type, @@ -170,7 +170,7 @@ ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, } ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, lldb::addr_t address, AddressType address_type, @@ -191,8 +191,8 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope case eAddressTypeLoad: m_value.SetValueType(Value::eValueTypeLoadAddress); break; case eAddressTypeHost: m_value.SetValueType(Value::eValueTypeHostAddress); break; } -// m_value.SetContext(Value::eContextTypeClangType, clang_type); - m_value.SetClangType (clang_type); +// m_value.SetContext(Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType (compiler_type); m_name = name; SetIsConstant (); SetValueIsValid(true); @@ -241,10 +241,10 @@ ValueObjectConstResult::~ValueObjectConstResult() { } -ClangASTType -ValueObjectConstResult::GetClangTypeImpl() +CompilerType +ValueObjectConstResult::GetCompilerTypeImpl() { - return m_value.GetClangType(); + return m_value.GetCompilerType(); } lldb::ValueType @@ -259,7 +259,7 @@ ValueObjectConstResult::GetByteSize() ExecutionContext exe_ctx(GetExecutionContextRef()); if (m_byte_size == 0) - SetByteSize(GetClangType().GetByteSize(exe_ctx.GetBestExecutionContextScope())); + SetByteSize(GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope())); return m_byte_size; } @@ -270,23 +270,24 @@ ValueObjectConstResult::SetByteSize (size_t size) } size_t -ValueObjectConstResult::CalculateNumChildren() +ValueObjectConstResult::CalculateNumChildren(uint32_t max) { - return GetClangType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } ConstString ValueObjectConstResult::GetTypeName() { if (m_type_name.IsEmpty()) - m_type_name = GetClangType().GetConstTypeName (); + m_type_name = GetCompilerType().GetConstTypeName (); return m_type_name; } ConstString ValueObjectConstResult::GetDisplayTypeName() { - return GetClangType().GetDisplayTypeName(); + return GetCompilerType().GetDisplayTypeName(); } bool @@ -313,7 +314,7 @@ ValueObjectConstResult::Dereference (Error &error) } lldb::ValueObjectSP -ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) { return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); } @@ -365,8 +366,16 @@ ValueObjectConstResult::GetDynamicValue (lldb::DynamicValueType use_dynamic) return ValueObjectSP(); } +lldb::ValueObjectSP +ValueObjectConstResult::Cast (const CompilerType &compiler_type) +{ + return m_impl.Cast(compiler_type); +} + lldb::LanguageType ValueObjectConstResult::GetPreferredDisplayLanguage () { - return lldb::eLanguageTypeUnknown; + if (m_preferred_display_language != lldb::eLanguageTypeUnknown) + return m_preferred_display_language; + return GetCompilerTypeImpl().GetMinimumLanguage(); } diff --git a/source/Core/ValueObjectConstResultCast.cpp b/source/Core/ValueObjectConstResultCast.cpp new file mode 100644 index 000000000000..8f0c0f1522f2 --- /dev/null +++ b/source/Core/ValueObjectConstResultCast.cpp @@ -0,0 +1,75 @@ +//===-- ValueObjectConstResultCast.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/ValueObjectConstResultCast.h" + +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectList.h" + +#include "lldb/Symbol/ClangASTContext.h" + +using namespace lldb_private; + +ValueObjectConstResultCast::ValueObjectConstResultCast( + ValueObject &parent, + const ConstString &name, + const CompilerType &cast_type, + lldb::addr_t live_address) : + ValueObjectCast (parent, name, cast_type), + m_impl(this, live_address) +{ + m_name = name; +} + +ValueObjectConstResultCast::~ValueObjectConstResultCast() +{ +} + +lldb::ValueObjectSP +ValueObjectConstResultCast::Dereference (Error &error) +{ + return m_impl.Dereference(error); +} + +lldb::ValueObjectSP +ValueObjectConstResultCast::GetSyntheticChildAtOffset(uint32_t offset, + const CompilerType& type, + bool can_create) +{ + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); +} + +lldb::ValueObjectSP +ValueObjectConstResultCast::AddressOf (Error &error) +{ + return m_impl.AddressOf(error); +} + +ValueObject * +ValueObjectConstResultCast::CreateChildAtIndex (size_t idx, + bool synthetic_array_member, + int32_t synthetic_index) +{ + return m_impl.CreateChildAtIndex( + idx, synthetic_array_member, synthetic_index); +} + +size_t +ValueObjectConstResultCast::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + return m_impl.GetPointeeData(data, item_idx, item_count); +} + +lldb::ValueObjectSP +ValueObjectConstResultCast::Cast (const CompilerType &compiler_type) +{ + return m_impl.Cast(compiler_type); +} diff --git a/source/Core/ValueObjectConstResultChild.cpp b/source/Core/ValueObjectConstResultChild.cpp index 64425ea50969..c93aedc22603 100644 --- a/source/Core/ValueObjectConstResultChild.cpp +++ b/source/Core/ValueObjectConstResultChild.cpp @@ -19,17 +19,19 @@ using namespace lldb_private; ValueObjectConstResultChild::ValueObjectConstResultChild ( ValueObject &parent, - const ClangASTType &clang_type, + const CompilerType &compiler_type, const ConstString &name, uint32_t byte_size, int32_t byte_offset, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool is_base_class, - bool is_deref_of_parent + bool is_deref_of_parent, + lldb::addr_t live_address, + uint64_t language_flags ) : ValueObjectChild (parent, - clang_type, + compiler_type, name, byte_size, byte_offset, @@ -37,8 +39,9 @@ ValueObjectConstResultChild::ValueObjectConstResultChild bitfield_bit_offset, is_base_class, is_deref_of_parent, - eAddressTypeLoad), - m_impl(this) + eAddressTypeLoad, + language_flags), + m_impl(this, live_address) { m_name = name; } @@ -54,7 +57,7 @@ ValueObjectConstResultChild::Dereference (Error &error) } lldb::ValueObjectSP -ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const CompilerType& type, bool can_create) { return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); } @@ -78,3 +81,9 @@ ValueObjectConstResultChild::GetPointeeData (DataExtractor& data, { return m_impl.GetPointeeData(data, item_idx, item_count); } + +lldb::ValueObjectSP +ValueObjectConstResultChild::Cast (const CompilerType &compiler_type) +{ + return m_impl.Cast(compiler_type); +} diff --git a/source/Core/ValueObjectConstResultImpl.cpp b/source/Core/ValueObjectConstResultImpl.cpp index 733d767b7ee1..85ac3f2c5fe5 100644 --- a/source/Core/ValueObjectConstResultImpl.cpp +++ b/source/Core/ValueObjectConstResultImpl.cpp @@ -11,13 +11,14 @@ #include "lldb/Core/ValueObjectChild.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectConstResultCast.h" #include "lldb/Core/ValueObjectConstResultChild.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -68,27 +69,29 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array uint32_t child_bitfield_bit_offset = 0; bool child_is_base_class = false; bool child_is_deref_of_parent = false; + uint64_t language_flags; const bool transparent_pointers = synthetic_array_member == false; - ClangASTType clang_type = m_impl_backend->GetClangType(); - ClangASTType child_clang_type; + CompilerType compiler_type = m_impl_backend->GetCompilerType(); + CompilerType child_compiler_type; ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef()); - child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - 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); - if (child_clang_type && child_byte_size) + child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx, + idx, + transparent_pointers, + omit_empty_base_classes, + 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) { if (synthetic_index) child_byte_offset += child_byte_size * synthetic_index; @@ -96,25 +99,25 @@ ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array ConstString child_name; if (!child_name_str.empty()) child_name.SetCString (child_name_str.c_str()); - + valobj = new ValueObjectConstResultChild (*m_impl_backend, - child_clang_type, + child_compiler_type, 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); - if (m_live_address != LLDB_INVALID_ADDRESS) - valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset); + child_is_deref_of_parent, + m_live_address == LLDB_INVALID_ADDRESS ? m_live_address : m_live_address+child_byte_offset, + language_flags); } return valobj; } lldb::ValueObjectSP -ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create) +ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const CompilerType& type, bool can_create) { if (m_impl_backend == NULL) return lldb::ValueObjectSP(); @@ -132,7 +135,7 @@ ValueObjectConstResultImpl::AddressOf (Error &error) return lldb::ValueObjectSP(); if (m_live_address != LLDB_INVALID_ADDRESS) { - ClangASTType clang_type(m_impl_backend->GetClangType()); + CompilerType compiler_type(m_impl_backend->GetCompilerType()); lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t))); @@ -140,10 +143,10 @@ ValueObjectConstResultImpl::AddressOf (Error &error) new_name.append(m_impl_backend->GetName().AsCString("")); ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef()); m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - clang_type.GetPointerType(), + compiler_type.GetPointerType(), ConstString(new_name.c_str()), buffer, - lldb::endian::InlHostByteOrder(), + endian::InlHostByteOrder(), exe_ctx.GetAddressByteSize()); m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); @@ -155,6 +158,17 @@ ValueObjectConstResultImpl::AddressOf (Error &error) return m_impl_backend->ValueObject::AddressOf(error); } +lldb::ValueObjectSP +ValueObjectConstResultImpl::Cast (const CompilerType &compiler_type) +{ + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + + ValueObjectConstResultCast *result_cast = new ValueObjectConstResultCast( + *m_impl_backend, m_impl_backend->GetName(), compiler_type, m_live_address); + return result_cast->GetSP(); +} + lldb::addr_t ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address, AddressType *address_type) diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index 89b98a1db1ba..0ac86a68f19f 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -20,7 +20,7 @@ #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -49,18 +49,18 @@ ValueObjectDynamicValue::~ValueObjectDynamicValue() m_owning_valobj_sp.reset(); } -ClangASTType -ValueObjectDynamicValue::GetClangTypeImpl () +CompilerType +ValueObjectDynamicValue::GetCompilerTypeImpl () { const bool success = UpdateValueIfNeeded(false); if (success) { if (m_dynamic_type_info.HasType()) - return m_value.GetClangType(); + return m_value.GetCompilerType(); else - return m_parent->GetClangType(); + return m_parent->GetCompilerType(); } - return m_parent->GetClangType(); + return m_parent->GetCompilerType(); } ConstString @@ -105,7 +105,7 @@ ValueObjectDynamicValue::GetDisplayTypeName() if (success) { if (m_dynamic_type_info.HasType()) - return GetClangType().GetDisplayTypeName(); + return GetCompilerType().GetDisplayTypeName(); if (m_dynamic_type_info.HasName()) return m_dynamic_type_info.GetName(); } @@ -113,13 +113,16 @@ ValueObjectDynamicValue::GetDisplayTypeName() } size_t -ValueObjectDynamicValue::CalculateNumChildren() +ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) - return GetClangType().GetNumChildren (true); + { + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; + } else - return m_parent->GetNumChildren(); + return m_parent->GetNumChildren(max); } uint64_t @@ -127,7 +130,10 @@ ValueObjectDynamicValue::GetByteSize() { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) - return m_value.GetValueByteSize(nullptr); + { + ExecutionContext exe_ctx (GetExecutionContextRef()); + return m_value.GetValueByteSize(nullptr, &exe_ctx); + } else return m_parent->GetByteSize(); } @@ -138,40 +144,6 @@ ValueObjectDynamicValue::GetValueType() const return m_parent->GetValueType(); } - -static TypeAndOrName -FixupTypeAndOrName (const TypeAndOrName& type_andor_name, - ValueObject& parent) -{ - TypeAndOrName ret(type_andor_name); - if (type_andor_name.HasType()) - { - // The type will always be the type of the dynamic object. If our parent's type was a pointer, - // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type - // should be okay... - ClangASTType orig_type = type_andor_name.GetClangASTType(); - ClangASTType corrected_type = orig_type; - if (parent.IsPointerType()) - corrected_type = orig_type.GetPointerType (); - else if (parent.IsPointerOrReferenceType()) - corrected_type = orig_type.GetLValueReferenceType (); - ret.SetClangASTType(corrected_type); - } - else /*if (m_dynamic_type_info.HasName())*/ - { - // If we are here we need to adjust our dynamic type name to include the correct & or * symbol - std::string corrected_name (type_andor_name.GetName().GetCString()); - if (parent.IsPointerType()) - corrected_name.append(" *"); - else if (parent.IsPointerOrReferenceType()) - corrected_name.append(" &"); - // the parent type should be a correctly pointer'ed or referenc'ed type - ret.SetClangASTType(parent.GetClangType()); - ret.SetName(corrected_name.c_str()); - } - return ret; -} - bool ValueObjectDynamicValue::UpdateValue () { @@ -210,25 +182,28 @@ ValueObjectDynamicValue::UpdateValue () TypeAndOrName class_type_or_name; Address dynamic_address; bool found_dynamic_type = false; + Value::ValueType value_type; + + LanguageRuntime *runtime = nullptr; lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) { - LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); + runtime = process->GetLanguageRuntime (known_type); if (runtime) - found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); + found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); } else { - LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); - if (cpp_runtime) - found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); + runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); + if (runtime) + found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); if (!found_dynamic_type) { - LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); - if (objc_runtime) - found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address); + runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); + if (runtime) + found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); } } @@ -237,11 +212,12 @@ ValueObjectDynamicValue::UpdateValue () m_update_point.SetUpdated(); - if (found_dynamic_type) + if (runtime && found_dynamic_type) { if (class_type_or_name.HasType()) { - m_type_impl = TypeImpl(m_parent->GetClangType(),FixupTypeAndOrName(class_type_or_name, *m_parent).GetClangASTType()); + m_type_impl = TypeImpl(m_parent->GetCompilerType(), + runtime->FixUpDynamicType(class_type_or_name, *m_parent).GetCompilerType()); } else { @@ -300,14 +276,13 @@ ValueObjectDynamicValue::UpdateValue () m_value.GetScalar() = load_address; } - m_dynamic_type_info = FixupTypeAndOrName(m_dynamic_type_info, *m_parent); + if (runtime) + m_dynamic_type_info = runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); //m_value.SetContext (Value::eContextTypeClangType, corrected_type); - m_value.SetClangType (m_dynamic_type_info.GetClangASTType()); + m_value.SetCompilerType (m_dynamic_type_info.GetCompilerType()); - // Our address is the location of the dynamic type stored in memory. It isn't a load address, - // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... - m_value.SetValueType(Value::eValueTypeScalar); + m_value.SetValueType(value_type); if (has_changed_type && log) log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(), @@ -421,3 +396,50 @@ ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error) SetNeedsUpdate(); return ret_val; } + +void +ValueObjectDynamicValue::SetPreferredDisplayLanguage (lldb::LanguageType lang) +{ + this->ValueObject::SetPreferredDisplayLanguage(lang); + if (m_parent) + m_parent->SetPreferredDisplayLanguage(lang); +} + +lldb::LanguageType +ValueObjectDynamicValue::GetPreferredDisplayLanguage () +{ + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) + { + if (m_parent) + return m_parent->GetPreferredDisplayLanguage(); + return lldb::eLanguageTypeUnknown; + } + else + return m_preferred_display_language; +} + +bool +ValueObjectDynamicValue::GetDeclaration (Declaration &decl) +{ + if (m_parent) + return m_parent->GetDeclaration(decl); + + return ValueObject::GetDeclaration(decl); +} + +uint64_t +ValueObjectDynamicValue::GetLanguageFlags () +{ + if (m_parent) + return m_parent->GetLanguageFlags(); + return this->ValueObject::GetLanguageFlags(); +} + +void +ValueObjectDynamicValue::SetLanguageFlags (uint64_t flags) +{ + if (m_parent) + m_parent->SetLanguageFlags(flags); + else + this->ValueObject::SetLanguageFlags(flags); +} diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index 9f1953138f62..b989710c95d5 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -46,7 +46,7 @@ ValueObjectSP ValueObjectMemory::Create (ExecutionContextScope *exe_scope, const char *name, const Address &address, - const ClangASTType &ast_type) + const CompilerType &ast_type) { return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP(); } @@ -58,7 +58,7 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, ValueObject(exe_scope), m_address (address), m_type_sp(type_sp), - m_clang_type() + m_compiler_type() { // Do not attempt to construct one of these objects with no variable! assert (m_type_sp.get() != NULL); @@ -90,21 +90,21 @@ ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, const char *name, const Address &address, - const ClangASTType &ast_type) : + const CompilerType &ast_type) : ValueObject(exe_scope), m_address (address), m_type_sp(), - m_clang_type(ast_type) + m_compiler_type(ast_type) { // Do not attempt to construct one of these objects with no variable! - assert (m_clang_type.GetASTContext()); - assert (m_clang_type.GetOpaqueQualType()); + assert (m_compiler_type.GetTypeSystem()); + assert (m_compiler_type.GetOpaqueQualType()); TargetSP target_sp (GetTargetSP()); SetName (ConstString(name)); -// m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); - m_value.SetClangType(m_clang_type); +// m_value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType()); + m_value.SetCompilerType(m_compiler_type); lldb::addr_t load_address = m_address.GetLoadAddress (target_sp.get()); if (load_address != LLDB_INVALID_ADDRESS) { @@ -131,12 +131,12 @@ ValueObjectMemory::~ValueObjectMemory() { } -ClangASTType -ValueObjectMemory::GetClangTypeImpl () +CompilerType +ValueObjectMemory::GetCompilerTypeImpl () { if (m_type_sp) - return m_type_sp->GetClangForwardType(); - return m_clang_type; + return m_type_sp->GetForwardCompilerType (); + return m_compiler_type; } ConstString @@ -144,24 +144,29 @@ ValueObjectMemory::GetTypeName() { if (m_type_sp) return m_type_sp->GetName(); - return m_clang_type.GetConstTypeName(); + return m_compiler_type.GetConstTypeName(); } ConstString ValueObjectMemory::GetDisplayTypeName() { if (m_type_sp) - return m_type_sp->GetClangForwardType().GetDisplayTypeName(); - return m_clang_type.GetDisplayTypeName(); + return m_type_sp->GetForwardCompilerType ().GetDisplayTypeName(); + return m_compiler_type.GetDisplayTypeName(); } size_t -ValueObjectMemory::CalculateNumChildren() +ValueObjectMemory::CalculateNumChildren(uint32_t max) { if (m_type_sp) - return m_type_sp->GetNumChildren(true); + { + auto child_count = m_type_sp->GetNumChildren(true); + return child_count <= max ? child_count : max; + } + const bool omit_empty_base_classes = true; - return m_clang_type.GetNumChildren (omit_empty_base_classes); + auto child_count = m_compiler_type.GetNumChildren (omit_empty_base_classes); + return child_count <= max ? child_count : max; } uint64_t @@ -169,7 +174,7 @@ ValueObjectMemory::GetByteSize() { if (m_type_sp) return m_type_sp->GetByteSize(); - return m_clang_type.GetByteSize (nullptr); + return m_compiler_type.GetByteSize (nullptr); } lldb::ValueType @@ -249,8 +254,8 @@ ValueObjectMemory::UpdateValue () value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); else { - //value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); - value.SetClangType(m_clang_type); + //value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType()); + value.SetCompilerType(m_compiler_type); } m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp index 0db1f0cd45cf..c7845cd03207 100644 --- a/source/Core/ValueObjectRegister.cpp +++ b/source/Core/ValueObjectRegister.cpp @@ -15,7 +15,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Module.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/ExecutionContext.h" @@ -42,10 +42,10 @@ ValueObjectRegisterContext::~ValueObjectRegisterContext() { } -ClangASTType -ValueObjectRegisterContext::GetClangTypeImpl () +CompilerType +ValueObjectRegisterContext::GetCompilerTypeImpl () { - return ClangASTType(); + return CompilerType(); } ConstString @@ -67,9 +67,10 @@ ValueObjectRegisterContext::GetQualifiedTypeName() } size_t -ValueObjectRegisterContext::CalculateNumChildren() +ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) { - return m_reg_ctx_sp->GetRegisterSetCount(); + auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount(); + return reg_set_count <= max ? reg_set_count : max; } uint64_t @@ -144,10 +145,10 @@ ValueObjectRegisterSet::~ValueObjectRegisterSet() { } -ClangASTType -ValueObjectRegisterSet::GetClangTypeImpl () +CompilerType +ValueObjectRegisterSet::GetCompilerTypeImpl () { - return ClangASTType(); + return CompilerType(); } ConstString @@ -163,11 +164,14 @@ ValueObjectRegisterSet::GetQualifiedTypeName() } size_t -ValueObjectRegisterSet::CalculateNumChildren() +ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) { const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); if (reg_set) - return reg_set->num_registers; + { + auto reg_count = reg_set->num_registers; + return reg_count <= max ? reg_count : max; + } return 0; } @@ -279,7 +283,7 @@ ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterCon m_reg_info (), m_reg_value (), m_type_name (), - m_clang_type () + m_compiler_type () { assert (reg_ctx_sp.get()); ConstructObject(reg_num); @@ -297,7 +301,7 @@ ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb m_reg_info (), m_reg_value (), m_type_name (), - m_clang_type () + m_compiler_type () { assert (reg_ctx); ConstructObject(reg_num); @@ -307,10 +311,10 @@ ValueObjectRegister::~ValueObjectRegister() { } -ClangASTType -ValueObjectRegister::GetClangTypeImpl () +CompilerType +ValueObjectRegister::GetCompilerTypeImpl () { - if (!m_clang_type.IsValid()) + if (!m_compiler_type.IsValid()) { ExecutionContext exe_ctx (GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); @@ -319,26 +323,29 @@ ValueObjectRegister::GetClangTypeImpl () Module *exe_module = target->GetExecutableModulePointer(); if (exe_module) { - m_clang_type = exe_module->GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding, - m_reg_info.byte_size * 8); + TypeSystem *type_system = exe_module->GetTypeSystemForLanguage (eLanguageTypeC); + if (type_system) + m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding, + m_reg_info.byte_size * 8); } } } - return m_clang_type; + return m_compiler_type; } ConstString ValueObjectRegister::GetTypeName() { if (m_type_name.IsEmpty()) - m_type_name = GetClangType().GetConstTypeName (); + m_type_name = GetCompilerType().GetConstTypeName (); return m_type_name; } size_t -ValueObjectRegister::CalculateNumChildren() +ValueObjectRegister::CalculateNumChildren(uint32_t max) { - return GetClangType().GetNumChildren(true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } uint64_t diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp index 867b52016298..0ccc4385e3cc 100644 --- a/source/Core/ValueObjectSyntheticFilter.cpp +++ b/source/Core/ValueObjectSyntheticFilter.cpp @@ -1,4 +1,4 @@ -//===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===// +//===-- ValueObjectSyntheticFilter.cpp --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/ValueObjectSyntheticFilter.h" - // C Includes // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/ValueObjectSyntheticFilter.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSynthetic.h" @@ -26,35 +25,34 @@ public: {} size_t - CalculateNumChildren() + CalculateNumChildren() override { return m_backend.GetNumChildren(); } lldb::ValueObjectSP - GetChildAtIndex (size_t idx) + GetChildAtIndex(size_t idx) override { return m_backend.GetChildAtIndex(idx, true); } - + size_t - GetIndexOfChildWithName (const ConstString &name) + GetIndexOfChildWithName(const ConstString &name) override { return m_backend.GetIndexOfChildWithName(name); } bool - MightHaveChildren () + MightHaveChildren() override { return true; } bool - Update() + Update() override { return false; } - }; ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) : @@ -78,14 +76,12 @@ ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::Synthetic CreateSynthFilter(); } -ValueObjectSynthetic::~ValueObjectSynthetic() -{ -} +ValueObjectSynthetic::~ValueObjectSynthetic() = default; -ClangASTType -ValueObjectSynthetic::GetClangTypeImpl () +CompilerType +ValueObjectSynthetic::GetCompilerTypeImpl () { - return m_parent->GetClangType(); + return m_parent->GetCompilerType(); } ConstString @@ -107,12 +103,16 @@ ValueObjectSynthetic::GetDisplayTypeName() } size_t -ValueObjectSynthetic::CalculateNumChildren() +ValueObjectSynthetic::CalculateNumChildren(uint32_t max) { UpdateValueIfNeeded(); if (m_synthetic_children_count < UINT32_MAX) - return m_synthetic_children_count; - return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren()); + return m_synthetic_children_count <= max ? m_synthetic_children_count : max; + + if (max < UINT32_MAX) + return m_synth_filter_ap->CalculateNumChildren(max); + else + return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max)); } lldb::ValueObjectSP @@ -217,12 +217,13 @@ ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create) ValueObject *valobj; if (m_children_byindex.GetValueForKey(idx, valobj) == false) { - if (can_create && m_synth_filter_ap.get() != NULL) + if (can_create && m_synth_filter_ap.get() != nullptr) { lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx); if (!synth_guy) return synth_guy; m_children_byindex.SetValueForKey(idx, synth_guy.get()); + synth_guy->SetPreferredDisplayLanguageIfNeeded(GetPreferredDisplayLanguage()); return synth_guy; } else @@ -253,7 +254,7 @@ ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) uint32_t found_index = UINT32_MAX; bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index); - if (!did_find && m_synth_filter_ap.get() != NULL) + if (!did_find && m_synth_filter_ap.get() != nullptr) { uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name); if (index == UINT32_MAX) @@ -261,7 +262,7 @@ ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) m_name_toindex.SetValueForKey(name.GetCString(), index); return index; } - else if (!did_find && m_synth_filter_ap.get() == NULL) + else if (!did_find && m_synth_filter_ap.get() == nullptr) return UINT32_MAX; else /*if (iter != m_name_toindex.end())*/ return found_index; @@ -314,3 +315,50 @@ ValueObjectSynthetic::SetFormat (lldb::Format format) this->ValueObject::SetFormat(format); this->ClearUserVisibleData(eClearUserVisibleDataItemsAll); } + +void +ValueObjectSynthetic::SetPreferredDisplayLanguage (lldb::LanguageType lang) +{ + this->ValueObject::SetPreferredDisplayLanguage(lang); + if (m_parent) + m_parent->SetPreferredDisplayLanguage(lang); +} + +lldb::LanguageType +ValueObjectSynthetic::GetPreferredDisplayLanguage () +{ + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) + { + if (m_parent) + return m_parent->GetPreferredDisplayLanguage(); + return lldb::eLanguageTypeUnknown; + } + else + return m_preferred_display_language; +} + +bool +ValueObjectSynthetic::GetDeclaration (Declaration &decl) +{ + if (m_parent) + return m_parent->GetDeclaration(decl); + + return ValueObject::GetDeclaration(decl); +} + +uint64_t +ValueObjectSynthetic::GetLanguageFlags () +{ + if (m_parent) + return m_parent->GetLanguageFlags(); + return this->ValueObject::GetLanguageFlags(); +} + +void +ValueObjectSynthetic::SetLanguageFlags (uint64_t flags) +{ + if (m_parent) + m_parent->SetLanguageFlags(flags); + else + this->ValueObject::SetLanguageFlags(flags); +} diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index c86bece42eb8..389b7c54243d 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -54,13 +54,13 @@ ValueObjectVariable::~ValueObjectVariable() { } -ClangASTType -ValueObjectVariable::GetClangTypeImpl () +CompilerType +ValueObjectVariable::GetCompilerTypeImpl () { Type *var_type = m_variable_sp->GetType(); if (var_type) - return var_type->GetClangForwardType(); - return ClangASTType(); + return var_type->GetForwardCompilerType (); + return CompilerType(); } ConstString @@ -77,7 +77,7 @@ ValueObjectVariable::GetDisplayTypeName() { Type * var_type = m_variable_sp->GetType(); if (var_type) - return var_type->GetClangForwardType().GetDisplayTypeName(); + return var_type->GetForwardCompilerType ().GetDisplayTypeName(); return ConstString(); } @@ -91,15 +91,16 @@ ValueObjectVariable::GetQualifiedTypeName() } size_t -ValueObjectVariable::CalculateNumChildren() +ValueObjectVariable::CalculateNumChildren(uint32_t max) { - ClangASTType type(GetClangType()); + CompilerType type(GetCompilerType()); if (!type.IsValid()) return 0; const bool omit_empty_base_classes = true; - return type.GetNumChildren(omit_empty_base_classes); + auto child_count = type.GetNumChildren(omit_empty_base_classes); + return child_count <= max ? child_count : max; } uint64_t @@ -107,7 +108,7 @@ ValueObjectVariable::GetByteSize() { ExecutionContext exe_ctx(GetExecutionContextRef()); - ClangASTType type(GetClangType()); + CompilerType type(GetCompilerType()); if (!type.IsValid()) return 0; @@ -168,15 +169,15 @@ ValueObjectVariable::UpdateValue () m_resolved_value = m_value; m_value.SetContext(Value::eContextTypeVariable, variable); - ClangASTType clang_type = GetClangType(); - if (clang_type.IsValid()) - m_value.SetClangType(clang_type); + CompilerType compiler_type = GetCompilerType(); + if (compiler_type.IsValid()) + m_value.SetCompilerType(compiler_type); Value::ValueType value_type = m_value.GetValueType(); Process *process = exe_ctx.GetProcessPtr(); const bool process_is_alive = process && process->IsAlive(); - const uint32_t type_info = clang_type.GetTypeInfo(); + const uint32_t type_info = compiler_type.GetTypeInfo(); const bool is_pointer_or_ref = (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; switch (value_type) diff --git a/source/DataFormatters/CF.cpp b/source/DataFormatters/CF.cpp deleted file mode 100644 index 6ab9013268bd..000000000000 --- a/source/DataFormatters/CF.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//===-- CF.cpp ----------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -bool -lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - time_t epoch = GetOSXEpoch(); - epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0); - tm *tm_date = localtime(&epoch); - if (!tm_date) - return false; - std::string buffer(1024,0); - if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) - return false; - stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str()); - return true; -} - -bool -lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint32_t count = 0; - - bool is_type_ok = false; // check to see if this is a CFBag we know about - if (descriptor->IsCFType()) - { - ConstString type_name(valobj.GetTypeName()); - if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) - { - if (valobj.IsPointerType()) - is_type_ok = true; - } - } - - if (is_type_ok == false) - { - StackFrameSP frame_sp(valobj.GetFrameSP()); - if (!frame_sp) - return false; - ValueObjectSP count_sp; - StreamString expr; - expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); - if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted) - return false; - if (!count_sp) - return false; - count = count_sp->GetValueAsUnsigned(0); - } - else - { - uint32_t offset = 2*ptr_size+4 + valobj_addr; - Error error; - count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); - if (error.Fail()) - return false; - } - stream.Printf("@\"%u value%s\"", - count,(count == 1 ? "" : "s")); - return true; -} - -bool -lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint32_t count = 0; - - bool is_type_ok = false; // check to see if this is a CFBag we know about - if (descriptor->IsCFType()) - { - ConstString type_name(valobj.GetTypeName()); - if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef")) - { - if (valobj.IsPointerType()) - is_type_ok = true; - } - } - - if (is_type_ok == false) - return false; - - Error error; - count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0); - addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error); - if (error.Fail()) - return false; - // make sure we do not try to read huge amounts of data - if (num_bytes > 1024) - num_bytes = 1024; - DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0)); - num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error); - if (error.Fail() || num_bytes == 0) - return false; - uint8_t *bytes = buffer_sp->GetBytes(); - for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++) - { - uint8_t byte = bytes[byte_idx]; - bool bit0 = (byte & 1) == 1; - bool bit1 = (byte & 2) == 2; - bool bit2 = (byte & 4) == 4; - bool bit3 = (byte & 8) == 8; - bool bit4 = (byte & 16) == 16; - bool bit5 = (byte & 32) == 32; - bool bit6 = (byte & 64) == 64; - bool bit7 = (byte & 128) == 128; - stream.Printf("%c%c%c%c %c%c%c%c ", - (bit7 ? '1' : '0'), - (bit6 ? '1' : '0'), - (bit5 ? '1' : '0'), - (bit4 ? '1' : '0'), - (bit3 ? '1' : '0'), - (bit2 ? '1' : '0'), - (bit1 ? '1' : '0'), - (bit0 ? '1' : '0')); - count -= 8; - } - { - // print the last byte ensuring we do not print spurious bits - uint8_t byte = bytes[num_bytes-1]; - bool bit0 = (byte & 1) == 1; - bool bit1 = (byte & 2) == 2; - bool bit2 = (byte & 4) == 4; - bool bit3 = (byte & 8) == 8; - bool bit4 = (byte & 16) == 16; - bool bit5 = (byte & 32) == 32; - bool bit6 = (byte & 64) == 64; - bool bit7 = (byte & 128) == 128; - if (count) - { - stream.Printf("%c",bit7 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit6 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit5 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit4 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit3 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit2 ? '1' : '0'); - count -= 1; - } - if (count) - { - stream.Printf("%c",bit1 ? '1' : '0'); - count -= 1; - } - if (count) - stream.Printf("%c",bit0 ? '1' : '0'); - } - return true; -} - -bool -lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint32_t count = 0; - - bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about - if (descriptor->IsCFType()) - { - ConstString type_name(valobj.GetTypeName()); - if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) - { - if (valobj.IsPointerType()) - is_type_ok = true; - } - } - - if (is_type_ok == false) - { - StackFrameSP frame_sp(valobj.GetFrameSP()); - if (!frame_sp) - return false; - ValueObjectSP count_sp; - StreamString expr; - expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); - if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp) != eExpressionCompleted) - return false; - if (!count_sp) - return false; - count = count_sp->GetValueAsUnsigned(0); - } - else - { - uint32_t offset = 2*ptr_size; - Error error; - count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); - if (error.Fail()) - return false; - } - stream.Printf("@\"%u item%s\"", - count,(count == 1 ? "" : "s")); - return true; -} diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp deleted file mode 100644 index 49eacee42f78..000000000000 --- a/source/DataFormatters/CXXFormatterFunctions.cpp +++ /dev/null @@ -1,1228 +0,0 @@ -//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" -#include "lldb/DataFormatters/StringPrinter.h" -#include "lldb/DataFormatters/TypeSummary.h" - -#include "llvm/Support/ConvertUTF.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/SectionLoadList.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" - -#include "lldb/Utility/ProcessStructReader.h" - -#include - -#if __ANDROID_NDK__ -#include -#endif - -#include "lldb/Host/Time.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -StackFrame* -lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx) -{ - StackFrame* frame = exe_ctx.GetFramePtr(); - if (frame) - return frame; - - Process* process = exe_ctx.GetProcessPtr(); - if (!process) - return nullptr; - - ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); - if (thread_sp) - return thread_sp->GetSelectedFrame().get(); - return nullptr; -} - -bool -lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj, - const char* target_type, - const char* selector, - uint64_t &value) -{ - if (!target_type || !*target_type) - return false; - if (!selector || !*selector) - return false; - StreamString expr; - expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); - ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); - lldb::ValueObjectSP result_sp; - Target* target = exe_ctx.GetTargetPtr(); - StackFrame* stack_frame = GetViableFrame(exe_ctx); - if (!target || !stack_frame) - return false; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(true); - - target->EvaluateExpression(expr.GetData(), - stack_frame, - result_sp, - options); - if (!result_sp) - return false; - value = result_sp->GetValueAsUnsigned(0); - return true; -} - -bool -lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj, - const char* target_type, - const char* selector, - Stream &stream) -{ - if (!target_type || !*target_type) - return false; - if (!selector || !*selector) - return false; - StreamString expr; - expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); - ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); - lldb::ValueObjectSP result_sp; - Target* target = exe_ctx.GetTargetPtr(); - StackFrame* stack_frame = GetViableFrame(exe_ctx); - if (!target || !stack_frame) - return false; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(true); - options.SetUseDynamic(lldb::eDynamicCanRunTarget); - - target->EvaluateExpression(expr.GetData(), - stack_frame, - result_sp, - options); - if (!result_sp) - return false; - stream.Printf("%s",result_sp->GetSummaryAsCString()); - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, - const char* return_type, - const char* selector, - uint64_t index) -{ - lldb::ValueObjectSP valobj_sp; - if (!return_type || !*return_type) - return valobj_sp; - if (!selector || !*selector) - return valobj_sp; - StreamString expr_path_stream; - valobj.GetExpressionPath(expr_path_stream, false); - StreamString expr; - expr.Printf("(%s)[%s %s:%" PRId64 "]",return_type,expr_path_stream.GetData(),selector,index); - ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); - lldb::ValueObjectSP result_sp; - Target* target = exe_ctx.GetTargetPtr(); - StackFrame* stack_frame = GetViableFrame(exe_ctx); - if (!target || !stack_frame) - return valobj_sp; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(true); - options.SetUseDynamic(lldb::eDynamicCanRunTarget); - - target->EvaluateExpression(expr.GetData(), - stack_frame, - valobj_sp, - options); - return valobj_sp; -} - -lldb::ValueObjectSP -lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, - const char* return_type, - const char* selector, - const char* key) -{ - lldb::ValueObjectSP valobj_sp; - if (!return_type || !*return_type) - return valobj_sp; - if (!selector || !*selector) - return valobj_sp; - if (!key || !*key) - return valobj_sp; - StreamString expr_path_stream; - valobj.GetExpressionPath(expr_path_stream, false); - StreamString expr; - expr.Printf("(%s)[%s %s:%s]",return_type,expr_path_stream.GetData(),selector,key); - ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); - lldb::ValueObjectSP result_sp; - Target* target = exe_ctx.GetTargetPtr(); - StackFrame* stack_frame = GetViableFrame(exe_ctx); - if (!target || !stack_frame) - return valobj_sp; - - EvaluateExpressionOptions options; - options.SetCoerceToId(false); - options.SetUnwindOnError(true); - options.SetKeepInMemory(true); - options.SetUseDynamic(lldb::eDynamicCanRunTarget); - - target->EvaluateExpression(expr.GetData(), - stack_frame, - valobj_sp, - options); - return valobj_sp; -} - -bool -lldb_private::formatters::FunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - std::string destination; - StreamString sstr; - AddressType func_ptr_address_type = eAddressTypeInvalid; - addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type); - if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) - { - switch (func_ptr_address_type) - { - case eAddressTypeInvalid: - case eAddressTypeFile: - case eAddressTypeHost: - break; - - case eAddressTypeLoad: - { - ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); - - Address so_addr; - Target *target = exe_ctx.GetTargetPtr(); - if (target && target->GetSectionLoadList().IsEmpty() == false) - { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) - { - so_addr.Dump (&sstr, - exe_ctx.GetBestExecutionContextScope(), - Address::DumpStyleResolvedDescription, - Address::DumpStyleSectionNameOffset); - } - } - } - break; - } - } - if (sstr.GetSize() > 0) - { - stream.Printf("(%s)", sstr.GetData()); - return true; - } - else - return false; -} - -bool -lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(valobj_addr); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('u'); - - if (!ReadStringAndDumpToStream(options)) - { - stream.Printf("Summary Unavailable"); - return true; - } - - return true; -} - -bool -lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(valobj_addr); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('U'); - - if (!ReadStringAndDumpToStream(options)) - { - stream.Printf("Summary Unavailable"); - return true; - } - - return true; -} - -bool -lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - lldb::addr_t data_addr = 0; - - if (valobj.IsPointerType()) - data_addr = valobj.GetValueAsUnsigned(0); - else if (valobj.IsArrayType()) - data_addr = valobj.GetAddressOf(); - - if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) - return false; - - clang::ASTContext* ast = valobj.GetClangType().GetASTContext(); - - if (!ast) - return false; - - ClangASTType wchar_clang_type = ClangASTContext::GetBasicType(ast, lldb::eBasicTypeWChar); - const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here - - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(data_addr); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('L'); - - switch (wchar_size) - { - case 8: - return ReadStringAndDumpToStream(options); - case 16: - return ReadStringAndDumpToStream(options); - case 32: - return ReadStringAndDumpToStream(options); - default: - stream.Printf("size for wchar_t is not valid"); - return true; - } - return true; -} - -bool -lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - DataExtractor data; - Error error; - valobj.GetData(data, error); - - if (error.Fail()) - return false; - - std::string value; - valobj.GetValueAsCString(lldb::eFormatUnicode16, value); - if (!value.empty()) - stream.Printf("%s ", value.c_str()); - - ReadBufferAndDumpToStreamOptions options(valobj); - options.SetData(data); - options.SetStream(&stream); - options.SetPrefixToken('u'); - options.SetQuote('\''); - options.SetSourceSize(1); - - return ReadBufferAndDumpToStream(options); -} - -bool -lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - DataExtractor data; - Error error; - valobj.GetData(data, error); - - if (error.Fail()) - return false; - - std::string value; - valobj.GetValueAsCString(lldb::eFormatUnicode32, value); - if (!value.empty()) - stream.Printf("%s ", value.c_str()); - - ReadBufferAndDumpToStreamOptions options(valobj); - options.SetData(data); - options.SetStream(&stream); - options.SetPrefixToken('U'); - options.SetQuote('\''); - options.SetSourceSize(1); - - return ReadBufferAndDumpToStream(options); -} - -bool -lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) -{ - DataExtractor data; - Error error; - valobj.GetData(data, error); - - if (error.Fail()) - return false; - - ReadBufferAndDumpToStreamOptions options(valobj); - options.SetData(data); - options.SetStream(&stream); - options.SetPrefixToken('L'); - options.SetQuote('\''); - options.SetSourceSize(1); - - return ReadBufferAndDumpToStream(options); -} - -// the field layout in a libc++ string (cap, side, data or data, size, cap) -enum LibcxxStringLayoutMode -{ - eLibcxxStringLayoutModeCSD = 0, - eLibcxxStringLayoutModeDSC = 1, - eLibcxxStringLayoutModeInvalid = 0xffff -}; - -// this function abstracts away the layout and mode details of a libc++ string -// and returns the address of the data and the size ready for callers to consume -static bool -ExtractLibcxxStringInfo (ValueObject& valobj, - ValueObjectSP &location_sp, - uint64_t& size) -{ - ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0})); - if (!D) - return false; - - ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0})); - - // this child should exist - if (!layout_decider) - return false; - - ConstString g_data_name("__data_"); - ConstString g_size_name("__size_"); - bool short_mode = false; // this means the string is in short-mode and the data is stored inline - LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; - uint64_t size_mode_value = 0; - - if (layout == eLibcxxStringLayoutModeDSC) - { - ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0})); - if (!size_mode) - return false; - - if (size_mode->GetName() != g_size_name) - { - // we are hitting the padding structure, move along - size_mode = D->GetChildAtIndexPath({1,1,1}); - if (!size_mode) - return false; - } - - size_mode_value = (size_mode->GetValueAsUnsigned(0)); - short_mode = ((size_mode_value & 0x80) == 0); - } - else - { - ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0})); - if (!size_mode) - return false; - - size_mode_value = (size_mode->GetValueAsUnsigned(0)); - short_mode = ((size_mode_value & 1) == 0); - } - - if (short_mode) - { - ValueObjectSP s(D->GetChildAtIndex(1, true)); - if (!s) - return false; - location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); - size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256); - return (location_sp.get() != nullptr); - } - else - { - ValueObjectSP l(D->GetChildAtIndex(0, true)); - if (!l) - return false; - // we can use the layout_decider object as the data pointer - location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true); - ValueObjectSP size_vo(l->GetChildAtIndex(1, true)); - if (!size_vo || !location_sp) - return false; - size = size_vo->GetValueAsUnsigned(0); - return true; - } -} - -bool -lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - uint64_t size = 0; - ValueObjectSP location_sp((ValueObject*)nullptr); - if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) - return false; - if (size == 0) - { - stream.Printf("L\"\""); - return true; - } - if (!location_sp) - return false; - return WCharStringSummaryProvider(*location_sp.get(), stream, options); -} - -bool -lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) -{ - uint64_t size = 0; - ValueObjectSP location_sp((ValueObject*)nullptr); - - if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) - return false; - - if (size == 0) - { - stream.Printf("\"\""); - return true; - } - - if (!location_sp) - return false; - - DataExtractor extractor; - if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) - size = std::min(size, valobj.GetTargetSP()->GetMaximumSizeOfStringSummary()); - location_sp->GetPointeeData(extractor, 0, size); - - ReadBufferAndDumpToStreamOptions options(valobj); - options.SetData(extractor); // none of this matters for a string - pass some defaults - options.SetStream(&stream); - options.SetPrefixToken(0); - options.SetQuote('"'); - options.SetSourceSize(size); - lldb_private::formatters::ReadBufferAndDumpToStream(options); - - return true; -} - -bool -lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0))); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - stream.Printf("%s",class_name); - return true; -} - -class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd -{ -public: - ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()) - { - } - - virtual size_t - CalculateNumChildren () - { - return 0; - } - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx) - { - return lldb::ValueObjectSP(); - } - - virtual bool - Update() - { - return false; - } - - virtual bool - MightHaveChildren () - { - return false; - } - - virtual size_t - GetIndexOfChildWithName (const ConstString &name) - { - return UINT32_MAX; - } - - virtual - ~ObjCClassSyntheticChildrenFrontEnd () - { - } -}; - -SyntheticChildrenFrontEnd* -lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp); -} - -template -bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - bool is_64bit = (process_sp->GetAddressByteSize() == 8); - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint64_t value = 0; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"NSConcreteData") || - !strcmp(class_name,"NSConcreteMutableData") || - !strcmp(class_name,"__NSCFData")) - { - uint32_t offset = (is_64bit ? 16 : 8); - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error); - if (error.Fail()) - return false; - } - else - { - if (!ExtractValueFromObjCExpression(valobj, "int", "length", value)) - return false; - } - - stream.Printf("%s%" PRIu64 " byte%s%s", - (needs_at ? "@\"" : ""), - value, - (value != 1 ? "s" : ""), - (needs_at ? "\"" : "")); - - return true; -} - -static bool -ReadAsciiBufferAndDumpToStream (lldb::addr_t location, - lldb::ProcessSP& process_sp, - Stream& dest, - uint32_t size = 0, - Error* error = NULL, - size_t *data_read = NULL, - char prefix_token = '@', - char quote = '"') -{ - Error my_error; - size_t my_data_read; - if (!process_sp || location == 0) - return false; - - if (!size) - size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); - else - size = std::min(size,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); - - lldb::DataBufferSP buffer_sp(new DataBufferHeap(size,0)); - - my_data_read = process_sp->ReadCStringFromMemory(location, (char*)buffer_sp->GetBytes(), size, my_error); - - if (error) - *error = my_error; - if (data_read) - *data_read = my_data_read; - - if (my_error.Fail()) - return false; - - dest.Printf("%c%c",prefix_token,quote); - - if (my_data_read) - dest.Printf("%s",(char*)buffer_sp->GetBytes()); - - dest.Printf("%c",quote); - - return true; -} - -bool -lldb_private::formatters::NSTaggedString_SummaryProvider (ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream) -{ - if (!descriptor) - return false; - uint64_t len_bits = 0, data_bits = 0; - if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr)) - return false; - - static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN - static const int g_SixbitMaxLen = 9; - static const int g_fiveBitMaxLen = 11; - - static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX"; - - if (len_bits > g_fiveBitMaxLen) - return false; - - // this is a fairly ugly trick - pretend that the numeric value is actually a char* - // this works under a few assumptions: - // little endian architecture - // sizeof(uint64_t) > g_MaxNonBitmaskedLen - if (len_bits <= g_MaxNonBitmaskedLen) - { - stream.Printf("@\"%s\"",(const char*)&data_bits); - return true; - } - - // if the data is bitmasked, we need to actually process the bytes - uint8_t bitmask = 0; - uint8_t shift_offset = 0; - - if (len_bits <= g_SixbitMaxLen) - { - bitmask = 0x03f; - shift_offset = 6; - } - else - { - bitmask = 0x01f; - shift_offset = 5; - } - - std::vector bytes; - bytes.resize(len_bits); - for (; len_bits > 0; data_bits >>= shift_offset, --len_bits) - { - uint8_t packed = data_bits & bitmask; - bytes.insert(bytes.begin(), sixBitToCharLookup[packed]); - } - - stream.Printf("@\"%s\"",&bytes[0]); - return true; -} - -static ClangASTType -GetNSPathStore2Type (Target &target) -{ - static ConstString g_type_name("__lldb_autogen_nspathstore2"); - - ClangASTContext *ast_ctx = target.GetScratchClangASTContext(); - - if (!ast_ctx) - return ClangASTType(); - - ClangASTType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); - ClangASTType uint32 = ast_ctx->GetIntTypeFromBitSize(32, false); - - return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, { - {"isa",voidstar}, - {"lengthAndRef",uint32}, - {"buffer",voidstar} - }); -} - -bool -lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo(); - // for a tagged pointer, the descriptor has everything we need - if (is_tagged_ptr) - return NSTaggedString_SummaryProvider(descriptor, stream); - - // if not a tagged pointer that we know about, try the normal route - uint64_t info_bits_location = valobj_addr + ptr_size; - if (process_sp->GetByteOrder() != lldb::eByteOrderLittle) - info_bits_location += 3; - - Error error; - - uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error); - if (error.Fail()) - return false; - - bool is_mutable = (info_bits & 1) == 1; - bool is_inline = (info_bits & 0x60) == 0; - bool has_explicit_length = (info_bits & (1 | 4)) != 4; - bool is_unicode = (info_bits & 0x10) == 0x10; - bool is_special = strcmp(class_name,"NSPathStore2") == 0; - bool has_null = (info_bits & 8) == 8; - - size_t explicit_length = 0; - if (!has_null && has_explicit_length && !is_special) - { - lldb::addr_t explicit_length_offset = 2*ptr_size; - if (is_mutable && !is_inline) - explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length; - else if (is_inline) - explicit_length = explicit_length + 0; // inline1.length; - else if (!is_inline && !is_mutable) - explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length; - else - explicit_length_offset = 0; - - if (explicit_length_offset) - { - explicit_length_offset = valobj_addr + explicit_length_offset; - explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error); - } - } - - if (strcmp(class_name,"NSString") && - strcmp(class_name,"CFStringRef") && - strcmp(class_name,"CFMutableStringRef") && - strcmp(class_name,"__NSCFConstantString") && - strcmp(class_name,"__NSCFString") && - strcmp(class_name,"NSCFConstantString") && - strcmp(class_name,"NSCFString") && - strcmp(class_name,"NSPathStore2")) - { - // not one of us - but tell me class name - stream.Printf("class name = %s",class_name); - return true; - } - - if (is_mutable) - { - uint64_t location = 2 * ptr_size + valobj_addr; - location = process_sp->ReadPointerFromMemory(location, error); - if (error.Fail()) - return false; - if (has_explicit_length && is_unicode) - { - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('@'); - options.SetQuote('"'); - options.SetSourceSize(explicit_length); - options.SetNeedsZeroTermination(false); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream(options); - } - else - { - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location+1); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('@'); - options.SetSourceSize(explicit_length); - options.SetNeedsZeroTermination(false); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream(options); - } - } - else if (is_inline && has_explicit_length && !is_unicode && !is_special && !is_mutable) - { - uint64_t location = 3 * ptr_size + valobj_addr; - return ReadAsciiBufferAndDumpToStream(location,process_sp,stream,explicit_length); - } - else if (is_unicode) - { - uint64_t location = valobj_addr + 2*ptr_size; - if (is_inline) - { - if (!has_explicit_length) - { - stream.Printf("found new combo"); - return true; - } - else - location += ptr_size; - } - else - { - location = process_sp->ReadPointerFromMemory(location, error); - if (error.Fail()) - return false; - } - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('@'); - options.SetQuote('"'); - options.SetSourceSize(explicit_length); - options.SetNeedsZeroTermination(has_explicit_length == false); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream (options); - } - else if (is_special) - { - ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP())); - explicit_length = reader.GetField(ConstString("lengthAndRef")) >> 20; - lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4; - - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('@'); - options.SetQuote('"'); - options.SetSourceSize(explicit_length); - options.SetNeedsZeroTermination(has_explicit_length == false); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream (options); - } - else if (is_inline) - { - uint64_t location = valobj_addr + 2*ptr_size; - if (!has_explicit_length) - location++; - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location); - options.SetProcessSP(process_sp); - options.SetStream(&stream); - options.SetPrefixToken('@'); - options.SetSourceSize(explicit_length); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream(options); - } - else - { - uint64_t location = valobj_addr + 2*ptr_size; - location = process_sp->ReadPointerFromMemory(location, error); - if (error.Fail()) - return false; - if (has_explicit_length && !has_null) - explicit_length++; // account for the fact that there is no NULL and we need to have one added - ReadStringAndDumpToStreamOptions options(valobj); - options.SetLocation(location); - options.SetProcessSP(process_sp); - options.SetPrefixToken('@'); - options.SetStream(&stream); - options.SetSourceSize(explicit_length); - options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); - return ReadStringAndDumpToStream(options); - } -} - -bool -lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - TargetSP target_sp(valobj.GetTargetSP()); - if (!target_sp) - return false; - uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize(); - uint64_t pointer_value = valobj.GetValueAsUnsigned(0); - if (!pointer_value) - return false; - pointer_value += addr_size; - ClangASTType type(valobj.GetClangType()); - ExecutionContext exe_ctx(target_sp,false); - ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type)); - if (!child_ptr_sp) - return false; - DataExtractor data; - Error error; - child_ptr_sp->GetData(data, error); - if (error.Fail()) - return false; - ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type)); - child_sp->GetValueAsUnsigned(0); - if (child_sp) - return NSStringSummaryProvider(*child_sp, stream, options); - return false; -} - -bool -lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - return NSAttributedStringSummaryProvider(valobj, stream, options); -} - -bool -lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - stream.Printf("%s",valobj.GetObjectDescription()); - return true; -} - -bool -lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - const uint32_t type_info = valobj.GetClangType().GetTypeInfo(); - - ValueObjectSP real_guy_sp = valobj.GetSP(); - - if (type_info & eTypeIsPointer) - { - Error err; - real_guy_sp = valobj.Dereference(err); - if (err.Fail() || !real_guy_sp) - return false; - } - else if (type_info & eTypeIsReference) - { - real_guy_sp = valobj.GetChildAtIndex(0, true); - if (!real_guy_sp) - return false; - } - uint64_t value = real_guy_sp->GetValueAsUnsigned(0); - if (value == 0) - { - stream.Printf("NO"); - return true; - } - stream.Printf("YES"); - return true; -} - -template -bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - lldb::ValueObjectSP valobj_sp; - - ClangASTType charstar (valobj.GetClangType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType()); - - if (!charstar) - return false; - - ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); - - if (is_sel_ptr) - { - lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - if (data_address == LLDB_INVALID_ADDRESS) - return false; - valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar); - } - else - { - DataExtractor data; - Error error; - valobj.GetData(data, error); - if (error.Fail()) - return false; - valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar); - } - - if (!valobj_sp) - return false; - - stream.Printf("%s",valobj_sp->GetSummaryAsCString()); - return true; -} - -// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001 -// this call gives the POSIX equivalent of the Cocoa epoch -time_t -lldb_private::formatters::GetOSXEpoch () -{ - static time_t epoch = 0; - if (!epoch) - { -#ifndef _WIN32 - tzset(); - tm tm_epoch; - tm_epoch.tm_sec = 0; - tm_epoch.tm_hour = 0; - tm_epoch.tm_min = 0; - tm_epoch.tm_mon = 0; - tm_epoch.tm_mday = 1; - tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why. - tm_epoch.tm_isdst = -1; - tm_epoch.tm_gmtoff = 0; - tm_epoch.tm_zone = NULL; - epoch = timegm(&tm_epoch); -#endif - } - return epoch; -} - -size_t -lldb_private::formatters::ExtractIndexFromString (const char* item_name) -{ - if (!item_name || !*item_name) - return UINT32_MAX; - if (*item_name != '[') - return UINT32_MAX; - item_name++; - char* endptr = NULL; - unsigned long int idx = ::strtoul(item_name, &endptr, 0); - if (idx == 0 && endptr == item_name) - return UINT32_MAX; - if (idx == ULONG_MAX) - return UINT32_MAX; - return idx; -} - -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, - ConstString item_name) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_item_name(item_name), -m_item_sp() -{ - if (valobj_sp) - Update(); -} - -bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() -{ - m_item_sp.reset(); - - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - - if (!valobj_sp) - return false; - - ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true)); - if (!item_ptr) - return false; - if (item_ptr->GetValueAsUnsigned(0) == 0) - return false; - Error err; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetClangType().GetPointeeType()); - if (err.Fail()) - m_item_sp.reset(); - return false; -} - -size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () -{ - return 1; -} - -lldb::ValueObjectSP -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx == 0) - return m_item_sp; - return lldb::ValueObjectSP(); -} - -bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (name == ConstString("item")) - return 0; - return UINT32_MAX; -} - -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd () -{ -} - -template bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - -template bool -lldb_private::formatters::NSDataSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - -template bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - -template bool -lldb_private::formatters::ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; diff --git a/source/DataFormatters/CXXFunctionPointer.cpp b/source/DataFormatters/CXXFunctionPointer.cpp new file mode 100644 index 000000000000..c9e0ccb29698 --- /dev/null +++ b/source/DataFormatters/CXXFunctionPointer.cpp @@ -0,0 +1,66 @@ +//===-- CXXFormatterFunctions.cpp---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/CXXFunctionPointer.h" + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Target.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::CXXFunctionPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ + std::string destination; + StreamString sstr; + AddressType func_ptr_address_type = eAddressTypeInvalid; + addr_t func_ptr_address = valobj.GetPointerValue (&func_ptr_address_type); + if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + { + switch (func_ptr_address_type) + { + case eAddressTypeInvalid: + case eAddressTypeFile: + case eAddressTypeHost: + break; + + case eAddressTypeLoad: + { + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + + Address so_addr; + Target *target = exe_ctx.GetTargetPtr(); + if (target && target->GetSectionLoadList().IsEmpty() == false) + { + if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + { + so_addr.Dump (&sstr, + exe_ctx.GetBestExecutionContextScope(), + Address::DumpStyleResolvedDescription, + Address::DumpStyleSectionNameOffset); + } + } + } + break; + } + } + if (sstr.GetSize() > 0) + { + stream.Printf("(%s)", sstr.GetData()); + return true; + } + else + return false; +} diff --git a/source/DataFormatters/Cocoa.cpp b/source/DataFormatters/Cocoa.cpp deleted file mode 100644 index 28f3d4f1d41b..000000000000 --- a/source/DataFormatters/Cocoa.cpp +++ /dev/null @@ -1,561 +0,0 @@ -//===-- Cocoa.cpp -------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -bool -lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"NSBundle")) - { - uint64_t offset = 5 * ptr_size; - ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); - - StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); - if (was_nsstring_ok && summary_stream.GetSize() > 0) - { - stream.Printf("%s",summary_stream.GetData()); - return true; - } - } - // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle] - // which is encoded differently and needs to be handled by running code - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream); -} - -bool -lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"__NSTimeZone")) - { - uint64_t offset = ptr_size; - ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true)); - StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); - if (was_nsstring_ok && summary_stream.GetSize() > 0) - { - stream.Printf("%s",summary_stream.GetData()); - return true; - } - } - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream); -} - -bool -lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"NSConcreteNotification")) - { - uint64_t offset = ptr_size; - ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetClangType(), true)); - StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); - if (was_nsstring_ok && summary_stream.GetSize() > 0) - { - stream.Printf("%s",summary_stream.GetData()); - return true; - } - } - // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle] - // which is encoded differently and needs to be handled by running code - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream); -} - -bool -lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - uint64_t port_number = 0; - - do - { - if (!strcmp(class_name,"NSMachPort")) - { - uint64_t offset = (ptr_size == 4 ? 12 : 20); - Error error; - port_number = process_sp->ReadUnsignedIntegerFromMemory(offset+valobj_addr, 4, 0, error); - if (error.Success()) - break; - } - if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number)) - return false; - } while (false); - - stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF)); - return true; -} - -bool -lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - uint64_t count = 0; - - do { - if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet")) - { - Error error; - uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error); - if (error.Fail()) - return false; - // this means the set is empty - count = 0 - if ((mode & 1) == 1) - { - count = 0; - break; - } - if ((mode & 2) == 2) - mode = 1; // this means the set only has one range - else - mode = 2; // this means the set has multiple ranges - if (mode == 1) - { - count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - } - else - { - // read a pointer to the data at 2*ptr_size - count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - // read the data at 2*ptr_size from the first location - count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - } - } - else - { - if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count)) - return false; - } - } while (false); - stream.Printf("%" PRIu64 " index%s", - count, - (count == 1 ? "" : "es")); - return true; -} - -bool -lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber")) - { - uint64_t value = 0; - uint64_t i_bits = 0; - if (descriptor->GetTaggedPointerInfo(&i_bits,&value)) - { - switch (i_bits) - { - case 0: - stream.Printf("(char)%hhd",(char)value); - break; - case 1: - case 4: - stream.Printf("(short)%hd",(short)value); - break; - case 2: - case 8: - stream.Printf("(int)%d",(int)value); - break; - case 3: - case 12: - stream.Printf("(long)%" PRId64,value); - break; - default: - return false; - } - return true; - } - else - { - Error error; - uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F); - uint64_t data_location = valobj_addr + 2*ptr_size; - uint64_t value = 0; - if (error.Fail()) - return false; - switch (data_type) - { - case 1: // 0B00001 - value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error); - if (error.Fail()) - return false; - stream.Printf("(char)%hhd",(char)value); - break; - case 2: // 0B0010 - value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error); - if (error.Fail()) - return false; - stream.Printf("(short)%hd",(short)value); - break; - case 3: // 0B0011 - value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); - if (error.Fail()) - return false; - stream.Printf("(int)%d",(int)value); - break; - case 17: // 0B10001 - data_location += 8; - case 4: // 0B0100 - value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); - if (error.Fail()) - return false; - stream.Printf("(long)%" PRId64,value); - break; - case 5: // 0B0101 - { - uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); - if (error.Fail()) - return false; - float flt_value = *((float*)&flt_as_int); - stream.Printf("(float)%f",flt_value); - break; - } - case 6: // 0B0110 - { - uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); - if (error.Fail()) - return false; - double dbl_value = *((double*)&dbl_as_lng); - stream.Printf("(double)%g",dbl_value); - break; - } - default: - return false; - } - return true; - } - } - else - { - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream); - } -} - -bool -lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (strcmp(class_name, "NSURL") == 0) - { - uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit) - uint64_t offset_base = offset_text + ptr_size; - ClangASTType type(valobj.GetClangType()); - ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true)); - ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true)); - if (!text) - return false; - if (text->GetValueAsUnsigned(0) == 0) - return false; - StreamString summary; - if (!NSStringSummaryProvider(*text, summary, options)) - return false; - if (base && base->GetValueAsUnsigned(0)) - { - if (summary.GetSize() > 0) - summary.GetString().resize(summary.GetSize()-1); - summary.Printf(" -- "); - StreamString base_summary; - if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0) - summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData()); - } - if (summary.GetSize()) - { - stream.Printf("%s",summary.GetData()); - return true; - } - } - else - { - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream); - } - return false; -} - -bool -lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint64_t date_value_bits = 0; - double date_value = 0.0; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (strcmp(class_name,"NSDate") == 0 || - strcmp(class_name,"__NSDate") == 0 || - strcmp(class_name,"__NSTaggedDate") == 0) - { - uint64_t info_bits=0,value_bits = 0; - if (descriptor->GetTaggedPointerInfo(&info_bits,&value_bits)) - { - date_value_bits = ((value_bits << 8) | (info_bits << 4)); - date_value = *((double*)&date_value_bits); - } - else - { - Error error; - date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error); - date_value = *((double*)&date_value_bits); - if (error.Fail()) - return false; - } - } - else if (!strcmp(class_name,"NSCalendarDate")) - { - Error error; - date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error); - date_value = *((double*)&date_value_bits); - if (error.Fail()) - return false; - } - else - { - if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false) - return false; - date_value = *((double*)&date_value_bits); - } - if (date_value == -63114076800) - { - stream.Printf("0001-12-30 00:00:00 +0000"); - return true; - } - // 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 - time_t epoch = GetOSXEpoch(); - epoch = epoch + (time_t)date_value; - tm *tm_date = gmtime(&epoch); - if (!tm_date) - return false; - std::string buffer(1024,0); - if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) - return false; - stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str()); - return true; -} diff --git a/source/DataFormatters/CoreMedia.cpp b/source/DataFormatters/CoreMedia.cpp deleted file mode 100644 index 5c33c0b69f72..000000000000 --- a/source/DataFormatters/CoreMedia.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//===-- CoreMedia.cpp --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/Flags.h" -#include "lldb/Symbol/ClangASTContext.h" - -#include - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -bool -lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(valobj.GetClangType().GetASTContext()); - if (!ast_ctx) - return false; - - // fetch children by offset to compensate for potential lack of debug info - auto int64_ty = ast_ctx->GetIntTypeFromBitSize(64, true); - auto int32_ty = ast_ctx->GetIntTypeFromBitSize(32, true); - - auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true)); - auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true)); - auto flags_sp(valobj.GetSyntheticChildAtOffset(12, int32_ty, true)); - - if (!value_sp || !timescale_sp || !flags_sp) - return false; - - auto value = value_sp->GetValueAsUnsigned(0); - auto timescale = (int32_t)timescale_sp->GetValueAsUnsigned(0); // the timescale specifies the fraction of a second each unit in the numerator occupies - auto flags = Flags(flags_sp->GetValueAsUnsigned(0) & 0x00000000000000FF); // the flags I need sit in the LSB - - const unsigned int FlagPositiveInf = 4; - const unsigned int FlagNegativeInf = 8; - const unsigned int FlagIndefinite = 16; - - if (flags.AnySet(FlagIndefinite)) - { - stream.Printf("indefinite"); - return true; - } - - if (flags.AnySet(FlagPositiveInf)) - { - stream.Printf("+oo"); - return true; - } - - if (flags.AnySet(FlagNegativeInf)) - { - stream.Printf("-oo"); - return true; - } - - if (timescale == 0) - return false; - - switch (timescale) - { - case 0: - return false; - case 1: - stream.Printf("%" PRId64 " seconds", value); - return true; - case 2: - stream.Printf("%" PRId64 " half seconds", value); - return true; - case 3: - stream.Printf("%" PRId64 " third%sof a second", value, value == 1 ? " " : "s "); - return true; - default: - stream.Printf("%" PRId64 " %" PRId32 "th%sof a second", value, timescale, value == 1 ? " " : "s "); - return true; - } -} diff --git a/source/DataFormatters/DataVisualization.cpp b/source/DataFormatters/DataVisualization.cpp index 361254185b31..14cf13d2f185 100644 --- a/source/DataFormatters/DataVisualization.cpp +++ b/source/DataFormatters/DataVisualization.cpp @@ -14,8 +14,6 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/Debugger.h" - using namespace lldb; using namespace lldb_private; @@ -133,6 +131,14 @@ DataVisualization::Categories::GetCategory (const ConstString &category, lldb::T return (entry.get() != NULL); } +bool +DataVisualization::Categories::GetCategory (lldb::LanguageType language, lldb::TypeCategoryImplSP &entry) +{ + if (LanguageCategory *lang_category = GetFormatManager().GetCategoryForLanguage(language)) + entry = lang_category->GetCategory(); + return (entry.get() != nullptr); +} + void DataVisualization::Categories::Add (const ConstString &category) { @@ -164,7 +170,14 @@ DataVisualization::Categories::Enable (const ConstString& category, { if (GetFormatManager().GetCategory(category)->IsEnabled()) GetFormatManager().DisableCategory(category); - GetFormatManager().EnableCategory(category, pos); + GetFormatManager().EnableCategory(category, pos, std::initializer_list()); +} + +void +DataVisualization::Categories::Enable (lldb::LanguageType lang_type) +{ + if (LanguageCategory* lang_category = GetFormatManager().GetCategoryForLanguage(lang_type)) + lang_category->Enable(); } void @@ -174,6 +187,13 @@ DataVisualization::Categories::Disable (const ConstString& category) GetFormatManager().DisableCategory(category); } +void +DataVisualization::Categories::Disable (lldb::LanguageType lang_type) +{ + if (LanguageCategory* lang_category = GetFormatManager().GetCategoryForLanguage(lang_type)) + lang_category->Disable(); +} + void DataVisualization::Categories::Enable (const lldb::TypeCategoryImplSP& category, TypeCategoryMap::Position pos) @@ -206,9 +226,9 @@ DataVisualization::Categories::DisableStar () } void -DataVisualization::Categories::LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton) +DataVisualization::Categories::ForEach (TypeCategoryMap::ForEachCallback callback) { - GetFormatManager().LoopThroughCategories(callback, callback_baton); + GetFormatManager().ForEachCategory(callback); } uint32_t @@ -248,9 +268,9 @@ DataVisualization::NamedSummaryFormats::Clear () } void -DataVisualization::NamedSummaryFormats::LoopThrough (TypeSummaryImpl::SummaryCallback callback, void* callback_baton) +DataVisualization::NamedSummaryFormats::ForEach (std::function callback) { - GetFormatManager().GetNamedSummaryContainer().LoopThrough(callback, callback_baton); + GetFormatManager().GetNamedSummaryContainer().ForEach(callback); } uint32_t diff --git a/source/DataFormatters/DumpValueObjectOptions.cpp b/source/DataFormatters/DumpValueObjectOptions.cpp new file mode 100644 index 000000000000..f3de1257bb80 --- /dev/null +++ b/source/DataFormatters/DumpValueObjectOptions.cpp @@ -0,0 +1,245 @@ +//===-- DumpValueObjectOptions.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/DumpValueObjectOptions.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +using namespace lldb; +using namespace lldb_private; + +DumpValueObjectOptions::DumpValueObjectOptions() : + m_summary_sp(), + m_root_valobj_name(), + m_max_ptr_depth(PointerDepth{PointerDepth::Mode::Default,0}), + m_decl_printing_helper(), + m_use_synthetic(true), + m_scope_already_checked(false), + m_flat_output(false), + m_ignore_cap(false), + m_show_types(false), + m_show_location(false), + m_use_objc(false), + m_hide_root_type(false), + m_hide_name(false), + m_hide_value(false), + m_run_validator(false), + m_use_type_display_name(true), + m_allow_oneliner_mode(true), + m_hide_pointer_value(false), + m_reveal_empty_aggregates(true) +{} + + +DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) : + DumpValueObjectOptions() +{ + m_use_dynamic = valobj.GetDynamicValueType(); + m_use_synthetic = valobj.IsSynthetic(); + m_varformat_language = valobj.GetPreferredDisplayLanguage(); +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetMaximumPointerDepth(PointerDepth depth) +{ + m_max_ptr_depth = depth; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetMaximumDepth(uint32_t depth) +{ + m_max_depth = depth; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetDeclPrintingHelper(DeclPrintingHelper helper) +{ + m_decl_printing_helper = helper; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetShowTypes(bool show) +{ + m_show_types = show; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetShowLocation(bool show) +{ + m_show_location = show; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetUseObjectiveC(bool use) +{ + m_use_objc = use; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetShowSummary(bool show) +{ + if (show == false) + SetOmitSummaryDepth(UINT32_MAX); + else + SetOmitSummaryDepth(0); + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetUseDynamicType(lldb::DynamicValueType dyn) +{ + m_use_dynamic = dyn; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetUseSyntheticValue(bool use_synthetic) +{ + m_use_synthetic = use_synthetic; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetScopeChecked(bool check) +{ + m_scope_already_checked = check; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetFlatOutput(bool flat) +{ + m_flat_output = flat; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetOmitSummaryDepth(uint32_t depth) +{ + m_omit_summary_depth = depth; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetIgnoreCap(bool ignore) +{ + m_ignore_cap = ignore; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetRawDisplay() +{ + SetUseSyntheticValue(false); + SetOmitSummaryDepth(UINT32_MAX); + SetIgnoreCap(true); + SetHideName(false); + SetHideValue(false); + SetUseTypeDisplayName(false); + SetAllowOnelinerMode(false); + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetFormat (lldb::Format format) +{ + m_format = format; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetSummary (lldb::TypeSummaryImplSP summary) +{ + m_summary_sp = summary; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetRootValueObjectName (const char* name) +{ + if (name) + m_root_valobj_name.assign(name); + else + m_root_valobj_name.clear(); + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetHideRootType (bool hide_root_type) +{ + m_hide_root_type = hide_root_type; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetHideName (bool hide_name) +{ + m_hide_name = hide_name; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetHideValue (bool hide_value) +{ + m_hide_value = hide_value; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetHidePointerValue (bool hide) +{ + m_hide_pointer_value = hide; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetVariableFormatDisplayLanguage (lldb::LanguageType lang) +{ + m_varformat_language = lang; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetRunValidator (bool run) +{ + m_run_validator = run; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetUseTypeDisplayName (bool dis) +{ + m_use_type_display_name = dis; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetAllowOnelinerMode (bool oneliner) +{ + m_allow_oneliner_mode = oneliner; + return *this; +} + +DumpValueObjectOptions& +DumpValueObjectOptions::SetRevealEmptyAggregates (bool reveal) +{ + m_reveal_empty_aggregates = reveal; + return *this; +} + diff --git a/source/DataFormatters/FormatClasses.cpp b/source/DataFormatters/FormatClasses.cpp index f27b45b30491..2e4acd175f1f 100644 --- a/source/DataFormatters/FormatClasses.cpp +++ b/source/DataFormatters/FormatClasses.cpp @@ -9,6 +9,8 @@ #include "lldb/DataFormatters/FormatClasses.h" +#include "lldb/DataFormatters/FormatManager.h" + // C Includes // C++ Includes @@ -20,3 +22,48 @@ using namespace lldb; using namespace lldb_private; +FormattersMatchData::FormattersMatchData (ValueObject& valobj, lldb::DynamicValueType use_dynamic) : + m_valobj(valobj), + m_dynamic_value_type(use_dynamic), + m_formatters_match_vector({},false), + m_type_for_cache(), + m_candidate_languages() +{ + m_type_for_cache = FormatManager::GetTypeForCache(valobj, use_dynamic); + m_candidate_languages = FormatManager::GetCandidateLanguages(valobj); +} + +FormattersMatchVector +FormattersMatchData::GetMatchesVector () +{ + if (!m_formatters_match_vector.second) + { + m_formatters_match_vector.second = true; + m_formatters_match_vector.first = FormatManager::GetPossibleMatches(m_valobj, m_dynamic_value_type); + } + return m_formatters_match_vector.first; +} + +ConstString +FormattersMatchData::GetTypeForCache () +{ + return m_type_for_cache; +} + +CandidateLanguagesVector +FormattersMatchData::GetCandidateLanguages () +{ + return m_candidate_languages; +} + +ValueObject& +FormattersMatchData::GetValueObject () +{ + return m_valobj; +} + +lldb::DynamicValueType +FormattersMatchData::GetDynamicValueType () +{ + return m_dynamic_value_type; +} diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp index 4e0fffbe6a1a..35a0468306fa 100644 --- a/source/DataFormatters/FormatManager.cpp +++ b/source/DataFormatters/FormatManager.cpp @@ -9,20 +9,23 @@ #include "lldb/DataFormatters/FormatManager.h" +#include "llvm/ADT/STLExtras.h" + // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Debugger.h" -#include "lldb/DataFormatters/CXXFormatterFunctions.h" +#include "lldb/Core/Log.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/LanguageCategory.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Platform.h" -#include "llvm/ADT/STLExtras.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; - +using namespace lldb_private::formatters; struct FormatInfo { @@ -63,6 +66,7 @@ g_format_infos[] = { eFormatVectorOfUInt32 , '\0' , "uint32_t[]" }, { eFormatVectorOfSInt64 , '\0' , "int64_t[]" }, { eFormatVectorOfUInt64 , '\0' , "uint64_t[]" }, + { eFormatVectorOfFloat16, '\0' , "float16[]" }, { eFormatVectorOfFloat32, '\0' , "float32[]" }, { eFormatVectorOfFloat64, '\0' , "float64[]" }, { eFormatVectorOfUInt128, '\0' , "uint128_t[]" }, @@ -119,6 +123,19 @@ GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format return false; } +void +FormatManager::Changed () +{ + ++m_last_revision; + m_format_cache.Clear (); + Mutex::Locker lang_locker(m_language_categories_mutex); + for (auto& iter : m_language_categories_map) + { + if (iter.second) + iter.second->GetFormatCache().Clear(); + } +} + bool FormatManager::GetFormatFromCString (const char *format_cstr, bool partial_match_ok, @@ -160,9 +177,33 @@ FormatManager::GetFormatAsCString (Format format) return NULL; } +void +FormatManager::EnableAllCategories () +{ + m_categories_map.EnableAllCategories (); + Mutex::Locker lang_locker(m_language_categories_mutex); + for (auto& iter : m_language_categories_map) + { + if (iter.second) + iter.second->Enable(); + } +} + +void +FormatManager::DisableAllCategories () +{ + m_categories_map.DisableAllCategories (); + Mutex::Locker lang_locker(m_language_categories_mutex); + for (auto& iter : m_language_categories_map) + { + if (iter.second) + iter.second->Disable(); + } +} + void FormatManager::GetPossibleMatches (ValueObject& valobj, - ClangASTType clang_type, + CompilerType compiler_type, uint32_t reason, lldb::DynamicValueType use_dynamic, FormattersMatchVector& entries, @@ -171,8 +212,8 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, bool did_strip_typedef, bool root_level) { - clang_type = clang_type.RemoveFastQualifiers(); - ConstString type_name(clang_type.GetConstTypeName()); + compiler_type = compiler_type.GetTypeForFormatters(); + ConstString type_name(compiler_type.GetConstTypeName()); if (valobj.GetBitfieldBitSize() > 0) { StreamString sstring; @@ -181,15 +222,19 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef}); reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; } - entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); - ConstString display_type_name(clang_type.GetDisplayTypeName()); - if (display_type_name != type_name) - entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); + if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) + { + entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); + + ConstString display_type_name(compiler_type.GetDisplayTypeName()); + if (display_type_name != type_name) + entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef}); + } - for (bool is_rvalue_ref = true, j = true; j && clang_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) + for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { - ClangASTType non_ref_type = clang_type.GetNonReferenceType(); + CompilerType non_ref_type = compiler_type.GetNonReferenceType(); GetPossibleMatches(valobj, non_ref_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, @@ -200,7 +245,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, did_strip_typedef); if (non_ref_type.IsTypedefType()) { - ClangASTType deffed_referenced_type = non_ref_type.GetTypedefedType(); + CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); GetPossibleMatches(valobj, deffed_referenced_type, @@ -213,9 +258,9 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, } } - if (clang_type.IsPointerType()) + if (compiler_type.IsPointerType()) { - ClangASTType non_ptr_type = clang_type.GetPointeeType(); + CompilerType non_ptr_type = compiler_type.GetPointeeType(); GetPossibleMatches(valobj, non_ptr_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, @@ -226,7 +271,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, did_strip_typedef); if (non_ptr_type.IsTypedefType()) { - ClangASTType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); + CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); GetPossibleMatches(valobj, deffed_pointed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, @@ -237,45 +282,26 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, true); // this is not exactly the usual meaning of stripping typedefs } } - bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL, - false, // no C - true); // yes ObjC - if (canBeObjCDynamic) + for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) { - if (use_dynamic != lldb::eNoDynamicValues) + if (Language* language = Language::FindPlugin(language_type)) { - do + for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) { - lldb::ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - break; - ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); - if (runtime == nullptr) - break; - ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj)); - if (!objc_class_sp) - break; - ConstString name (objc_class_sp->GetClassName()); - entries.push_back({name,reason | lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery,did_strip_ptr,did_strip_ref,did_strip_typedef}); - } while (false); + entries.push_back({candidate, + reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin, + did_strip_ptr, + did_strip_ref, + did_strip_typedef}); + } } - - ClangASTType non_ptr_type = clang_type.GetPointeeType(); - GetPossibleMatches(valobj, - non_ptr_type, - reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, - use_dynamic, - entries, - true, - did_strip_ref, - did_strip_typedef); } - + // try to strip typedef chains - if (clang_type.IsTypedefType()) + if (compiler_type.IsTypedefType()) { - ClangASTType deffed_type = clang_type.GetTypedefedType(); + CompilerType deffed_type = compiler_type.GetTypedefedType(); GetPossibleMatches(valobj, deffed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, @@ -289,15 +315,15 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, if (root_level) { do { - if (!clang_type.IsValid()) + if (!compiler_type.IsValid()) break; - ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType(); - if (!unqual_clang_ast_type.IsValid()) + CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType(); + if (!unqual_compiler_ast_type.IsValid()) break; - if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType()) + if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) GetPossibleMatches (valobj, - unqual_clang_ast_type, + unqual_compiler_ast_type, reason, use_dynamic, entries, @@ -313,7 +339,7 @@ FormatManager::GetPossibleMatches (ValueObject& valobj, lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); if (static_value_sp) GetPossibleMatches(*static_value_sp.get(), - static_value_sp->GetClangType(), + static_value_sp->GetCompilerType(), reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue, use_dynamic, entries, @@ -472,6 +498,21 @@ FormatManager::GetValidatorForType (lldb::TypeNameSpecifierImplSP type_sp) return validator_chosen_sp; } +void +FormatManager::ForEachCategory(TypeCategoryMap::ForEachCallback callback) +{ + m_categories_map.ForEach(callback); + Mutex::Locker locker(m_language_categories_mutex); + for (const auto& entry : m_language_categories_map) + { + if (auto category_sp = entry.second->GetCategory()) + { + if (!callback(category_sp)) + break; + } + } +} + lldb::TypeCategoryImplSP FormatManager::GetCategory (const ConstString& category_name, bool can_create) @@ -510,6 +551,7 @@ FormatManager::GetSingleItemFormat(lldb::Format vector_format) case eFormatVectorOfUInt128: return eFormatHex; + case eFormatVectorOfFloat16: case eFormatVectorOfFloat32: case eFormatVectorOfFloat64: return eFormatFloat; @@ -534,6 +576,22 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) if (valobj.GetNumChildren() == 0) return false; + // ask the type if it has any opinion about this + // eLazyBoolCalculate == no opinion; other values should be self explanatory + CompilerType compiler_type(valobj.GetCompilerType()); + if (compiler_type.IsValid()) + { + switch (compiler_type.ShouldPrintAsOneLiner(&valobj)) + { + case eLazyBoolNo: + return false; + case eLazyBoolYes: + return true; + case eLazyBoolCalculate: + break; + } + } + size_t total_children_name_len = 0; for (size_t idx = 0; @@ -545,6 +603,23 @@ FormatManager::ShouldPrintAsOneLiner (ValueObject& valobj) // something is wrong here - bail out if (!child_sp) return false; + + // also ask the child's type if it has any opinion + CompilerType child_compiler_type(child_sp->GetCompilerType()); + if (child_compiler_type.IsValid()) + { + switch (child_compiler_type.ShouldPrintAsOneLiner(child_sp.get())) + { + case eLazyBoolYes: + // an opinion of yes is only binding for the child, so keep going + case eLazyBoolCalculate: + break; + case eLazyBoolNo: + // but if the child says no, then it's a veto on the whole thing + return false; + } + } + // if we decided to define synthetic children for a type, we probably care enough // to show them, but avoid nesting children in children if (child_sp->GetSyntheticChildren().get() != nullptr) @@ -596,53 +671,86 @@ FormatManager::GetValidTypeName (const ConstString& type) } ConstString -GetTypeForCache (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetTypeForCache (ValueObject& valobj, + lldb::DynamicValueType use_dynamic) { - if (use_dynamic == lldb::eNoDynamicValues) + ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(use_dynamic, valobj.IsSynthetic()); + if (valobj_sp && valobj_sp->GetCompilerType().IsValid()) { - if (valobj.IsDynamic()) - { - if (valobj.GetStaticValue()) - return valobj.GetStaticValue()->GetQualifiedTypeName(); - else - return ConstString(); - } - else - return valobj.GetQualifiedTypeName(); + if (!valobj_sp->GetCompilerType().IsMeaninglessWithoutDynamicResolution()) + return valobj_sp->GetQualifiedTypeName(); } - if (valobj.IsDynamic()) - return valobj.GetQualifiedTypeName(); - if (valobj.GetDynamicValue(use_dynamic)) - return valobj.GetDynamicValue(use_dynamic)->GetQualifiedTypeName(); return ConstString(); } +std::vector +FormatManager::GetCandidateLanguages (ValueObject& valobj) +{ + lldb::LanguageType lang_type = valobj.GetObjectRuntimeLanguage(); + return GetCandidateLanguages(lang_type); +} + +std::vector +FormatManager::GetCandidateLanguages (lldb::LanguageType lang_type) +{ + switch (lang_type) + { + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC89: + case lldb::eLanguageTypeC99: + case lldb::eLanguageTypeC11: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeC_plus_plus_03: + case lldb::eLanguageTypeC_plus_plus_11: + case lldb::eLanguageTypeC_plus_plus_14: + return {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC}; + default: + return {lang_type}; + } +} + +LanguageCategory* +FormatManager::GetCategoryForLanguage (lldb::LanguageType lang_type) +{ + Mutex::Locker locker(m_language_categories_mutex); + auto iter = m_language_categories_map.find(lang_type), end = m_language_categories_map.end(); + if (iter != end) + return iter->second.get(); + LanguageCategory* lang_category = new LanguageCategory(lang_type); + m_language_categories_map[lang_type] = LanguageCategory::UniquePointer(lang_category); + return lang_category; +} + lldb::TypeFormatImplSP -FormatManager::GetHardcodedFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetHardcodedFormat (FormattersMatchData& match_data) { - for (const auto& candidate: m_hardcoded_formats) + TypeFormatImplSP retval_sp; + + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { - auto result = candidate(valobj,use_dynamic,*this); - if (result) - return result; + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->GetHardcoded(*this, match_data, retval_sp)) + break; + } } - return nullptr; + + return retval_sp; } lldb::TypeFormatImplSP FormatManager::GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { + FormattersMatchData match_data(valobj, use_dynamic); + TypeFormatImplSP retval; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - ConstString valobj_type(GetTypeForCache(valobj, use_dynamic)); - if (valobj_type) + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (match_data.GetTypeForCache()) { if (log) - log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", valobj_type.AsCString("")); - if (m_format_cache.GetFormat(valobj_type,retval)) + log->Printf("\n\n[FormatManager::GetFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("")); + if (m_format_cache.GetFormat(match_data.GetTypeForCache(),retval)) { if (log) { @@ -655,21 +763,41 @@ FormatManager::GetFormat (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetFormat] Cache search failed. Going normal route"); } - retval = m_categories_map.GetFormat(valobj, use_dynamic); + + retval = m_categories_map.GetFormat(match_data); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetFormat] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(match_data, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetFormat] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) log->Printf("[FormatManager::GetFormat] Search failed. Giving hardcoded a chance."); - retval = GetHardcodedFormat(valobj, use_dynamic); + retval = GetHardcodedFormat(match_data); } - if (valobj_type && (!retval || !retval->NonCacheable())) + if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { if (log) log->Printf("[FormatManager::GetFormat] Caching %p for type %s", static_cast(retval.get()), - valobj_type.AsCString("")); - m_format_cache.SetFormat(valobj_type,retval); + match_data.GetTypeForCache().AsCString("")); + m_format_cache.SetFormat(match_data.GetTypeForCache(),retval); } if (log && log->GetDebug()) log->Printf("[FormatManager::GetFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); @@ -677,30 +805,35 @@ FormatManager::GetFormat (ValueObject& valobj, } lldb::TypeSummaryImplSP -FormatManager::GetHardcodedSummaryFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetHardcodedSummaryFormat (FormattersMatchData& match_data) { - for (const auto& candidate: m_hardcoded_summaries) + TypeSummaryImplSP retval_sp; + + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { - auto result = candidate(valobj,use_dynamic,*this); - if (result) - return result; + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->GetHardcoded(*this, match_data, retval_sp)) + break; + } } - return nullptr; + + return retval_sp; } lldb::TypeSummaryImplSP FormatManager::GetSummaryFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { + FormattersMatchData match_data(valobj, use_dynamic); + TypeSummaryImplSP retval; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - ConstString valobj_type(GetTypeForCache(valobj, use_dynamic)); - if (valobj_type) + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (match_data.GetTypeForCache()) { if (log) - log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", valobj_type.AsCString("")); - if (m_format_cache.GetSummary(valobj_type,retval)) + log->Printf("\n\n[FormatManager::GetSummaryFormat] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("")); + if (m_format_cache.GetSummary(match_data.GetTypeForCache(),retval)) { if (log) { @@ -713,21 +846,41 @@ FormatManager::GetSummaryFormat (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetSummaryFormat] Cache search failed. Going normal route"); } - retval = m_categories_map.GetSummaryFormat(valobj, use_dynamic); + + retval = m_categories_map.GetSummaryFormat(match_data); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(match_data, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetSummaryFormat] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) log->Printf("[FormatManager::GetSummaryFormat] Search failed. Giving hardcoded a chance."); - retval = GetHardcodedSummaryFormat(valobj, use_dynamic); + retval = GetHardcodedSummaryFormat(match_data); } - if (valobj_type && (!retval || !retval->NonCacheable())) + if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { if (log) log->Printf("[FormatManager::GetSummaryFormat] Caching %p for type %s", static_cast(retval.get()), - valobj_type.AsCString("")); - m_format_cache.SetSummary(valobj_type,retval); + match_data.GetTypeForCache().AsCString("")); + m_format_cache.SetSummary(match_data.GetTypeForCache(),retval); } if (log && log->GetDebug()) log->Printf("[FormatManager::GetSummaryFormat] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); @@ -736,30 +889,35 @@ FormatManager::GetSummaryFormat (ValueObject& valobj, #ifndef LLDB_DISABLE_PYTHON lldb::SyntheticChildrenSP -FormatManager::GetHardcodedSyntheticChildren (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetHardcodedSyntheticChildren (FormattersMatchData& match_data) { - for (const auto& candidate: m_hardcoded_synthetics) + SyntheticChildrenSP retval_sp; + + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { - auto result = candidate(valobj,use_dynamic,*this); - if (result) - return result; + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->GetHardcoded(*this, match_data, retval_sp)) + break; + } } - return nullptr; + + return retval_sp; } lldb::SyntheticChildrenSP FormatManager::GetSyntheticChildren (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { + FormattersMatchData match_data(valobj, use_dynamic); + SyntheticChildrenSP retval; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - ConstString valobj_type(GetTypeForCache(valobj, use_dynamic)); - if (valobj_type) + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (match_data.GetTypeForCache()) { if (log) - log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", valobj_type.AsCString("")); - if (m_format_cache.GetSynthetic(valobj_type,retval)) + log->Printf("\n\n[FormatManager::GetSyntheticChildren] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("")); + if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(),retval)) { if (log) { @@ -772,21 +930,41 @@ FormatManager::GetSyntheticChildren (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetSyntheticChildren] Cache search failed. Going normal route"); } - retval = m_categories_map.GetSyntheticChildren(valobj, use_dynamic); + + retval = m_categories_map.GetSyntheticChildren(match_data); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(match_data, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetSyntheticChildren] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) log->Printf("[FormatManager::GetSyntheticChildren] Search failed. Giving hardcoded a chance."); - retval = GetHardcodedSyntheticChildren(valobj, use_dynamic); + retval = GetHardcodedSyntheticChildren(match_data); } - if (valobj_type && (!retval || !retval->NonCacheable())) + if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { if (log) log->Printf("[FormatManager::GetSyntheticChildren] Caching %p for type %s", static_cast(retval.get()), - valobj_type.AsCString("")); - m_format_cache.SetSynthetic(valobj_type,retval); + match_data.GetTypeForCache().AsCString("")); + m_format_cache.SetSynthetic(match_data.GetTypeForCache(),retval); } if (log && log->GetDebug()) log->Printf("[FormatManager::GetSyntheticChildren] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); @@ -798,14 +976,15 @@ lldb::TypeValidatorImplSP FormatManager::GetValidator (ValueObject& valobj, lldb::DynamicValueType use_dynamic) { + FormattersMatchData match_data(valobj, use_dynamic); + TypeValidatorImplSP retval; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - ConstString valobj_type(GetTypeForCache(valobj, use_dynamic)); - if (valobj_type) + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (match_data.GetTypeForCache()) { if (log) - log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", valobj_type.AsCString("")); - if (m_format_cache.GetValidator(valobj_type,retval)) + log->Printf("\n\n[FormatManager::GetValidator] Looking into cache for type %s", match_data.GetTypeForCache().AsCString("")); + if (m_format_cache.GetValidator(match_data.GetTypeForCache(),retval)) { if (log) { @@ -818,21 +997,41 @@ FormatManager::GetValidator (ValueObject& valobj, if (log) log->Printf("[FormatManager::GetValidator] Cache search failed. Going normal route"); } - retval = m_categories_map.GetValidator(valobj, use_dynamic); + + retval = m_categories_map.GetValidator(match_data); + if (!retval) + { + if (log) + log->Printf("[FormatManager::GetValidator] Search failed. Giving language a chance."); + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) + { + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->Get(match_data, retval)) + break; + } + } + if (retval) + { + if (log) + log->Printf("[FormatManager::GetValidator] Language search success. Returning."); + return retval; + } + } if (!retval) { if (log) log->Printf("[FormatManager::GetValidator] Search failed. Giving hardcoded a chance."); - retval = GetHardcodedValidator(valobj, use_dynamic); + retval = GetHardcodedValidator(match_data); } - if (valobj_type && (!retval || !retval->NonCacheable())) + if (match_data.GetTypeForCache() && (!retval || !retval->NonCacheable())) { if (log) log->Printf("[FormatManager::GetValidator] Caching %p for type %s", static_cast(retval.get()), - valobj_type.AsCString("")); - m_format_cache.SetValidator(valobj_type,retval); + match_data.GetTypeForCache().AsCString("")); + m_format_cache.SetValidator(match_data.GetTypeForCache(),retval); } if (log && log->GetDebug()) log->Printf("[FormatManager::GetValidator] Cache hits: %" PRIu64 " - Cache Misses: %" PRIu64, m_format_cache.GetCacheHits(), m_format_cache.GetCacheMisses()); @@ -840,313 +1039,43 @@ FormatManager::GetValidator (ValueObject& valobj, } lldb::TypeValidatorImplSP -FormatManager::GetHardcodedValidator (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +FormatManager::GetHardcodedValidator (FormattersMatchData& match_data) { - for (const auto& candidate: m_hardcoded_validators) + TypeValidatorImplSP retval_sp; + + for (lldb::LanguageType lang_type : match_data.GetCandidateLanguages()) { - auto result = candidate(valobj,use_dynamic,*this); - if (result) - return result; + if (LanguageCategory* lang_category = GetCategoryForLanguage(lang_type)) + { + if (lang_category->GetHardcoded(*this, match_data, retval_sp)) + break; + } } - return nullptr; + + return retval_sp; } FormatManager::FormatManager() : + m_last_revision(0), m_format_cache(), + m_language_categories_mutex(Mutex::eMutexTypeRecursive), + m_language_categories_map(), m_named_summaries_map(this), - m_last_revision(0), m_categories_map(this), m_default_category_name(ConstString("default")), m_system_category_name(ConstString("system")), - m_gnu_cpp_category_name(ConstString("gnu-libstdc++")), - m_libcxx_category_name(ConstString("libcxx")), - m_objc_category_name(ConstString("objc")), - m_corefoundation_category_name(ConstString("CoreFoundation")), - m_coregraphics_category_name(ConstString("CoreGraphics")), - m_coreservices_category_name(ConstString("CoreServices")), - m_vectortypes_category_name(ConstString("VectorTypes")), - m_appkit_category_name(ConstString("AppKit")), - m_coremedia_category_name(ConstString("CoreMedia")), - m_hardcoded_formats(), - m_hardcoded_summaries(), - m_hardcoded_synthetics(), - m_hardcoded_validators() - + m_vectortypes_category_name(ConstString("VectorTypes")) { LoadSystemFormatters(); - LoadLibStdcppFormatters(); - LoadLibcxxFormatters(); - LoadObjCFormatters(); - LoadCoreMediaFormatters(); - LoadHardcodedFormatters(); - - EnableCategory(m_objc_category_name,TypeCategoryMap::Last); - EnableCategory(m_corefoundation_category_name,TypeCategoryMap::Last); - EnableCategory(m_appkit_category_name,TypeCategoryMap::Last); - EnableCategory(m_coreservices_category_name,TypeCategoryMap::Last); - EnableCategory(m_coregraphics_category_name,TypeCategoryMap::Last); - EnableCategory(m_coremedia_category_name,TypeCategoryMap::Last); - EnableCategory(m_gnu_cpp_category_name,TypeCategoryMap::Last); - EnableCategory(m_libcxx_category_name,TypeCategoryMap::Last); - EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last); - EnableCategory(m_system_category_name,TypeCategoryMap::Last); -} - -static void -AddFormat (TypeCategoryImpl::SharedPointer category_sp, - lldb::Format format, - ConstString type_name, - TypeFormatImpl::Flags flags, - bool regex = false) -{ - lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags)); - - if (regex) - category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp); - else - category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp); -} - - -static void -AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, - const char* string, - ConstString type_name, - TypeSummaryImpl::Flags flags, - bool regex = false) -{ - lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, - string)); - - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); -} - -static void -AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp, - ConstString type_name, - TypeSummaryImpl::Flags flags, - bool regex = false) -{ - flags.SetShowMembersOneLiner(true); - lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, "")); - - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); -} - -#ifndef LLDB_DISABLE_PYTHON -static void -AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp, - CXXFunctionSummaryFormat::Callback funct, - const char* description, - ConstString type_name, - TypeSummaryImpl::Flags flags, - bool regex = false) -{ - lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description)); - if (regex) - category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); - else - category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); -} -#endif - -#ifndef LLDB_DISABLE_PYTHON -static void AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp, - CXXSyntheticChildren::CreateFrontEndCallback generator, - const char* description, - ConstString type_name, - ScriptedSyntheticChildren::Flags flags, - bool regex = false) -{ - lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator)); - if (regex) - category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp); - else - category_sp->GetTypeSyntheticsContainer()->Add(type_name,synth_sp); -} -#endif - -#ifndef LLDB_DISABLE_PYTHON -static void AddFilter (TypeCategoryImpl::SharedPointer category_sp, - std::vector children, - const char* description, - ConstString type_name, - ScriptedSyntheticChildren::Flags flags, - bool regex = false) -{ - TypeFilterImplSP filter_sp(new TypeFilterImpl(flags)); - for (auto child : children) - filter_sp->AddExpressionPath(child); - if (regex) - category_sp->GetRegexTypeFiltersContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), filter_sp); - else - category_sp->GetTypeFiltersContainer()->Add(type_name,filter_sp); -} -#endif - -void -FormatManager::LoadLibStdcppFormatters() -{ - TypeSummaryImpl::Flags stl_summary_flags; - stl_summary_flags.SetCascades(true) - .SetSkipPointers(false) - .SetSkipReferences(false) - .SetDontShowChildren(true) - .SetDontShowValue(true) - .SetShowMembersOneLiner(false) - .SetHideItemNames(false); - - lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags, - "${var._M_dataplus._M_p}")); - - TypeCategoryImpl::SharedPointer gnu_category_sp = GetCategory(m_gnu_cpp_category_name); - - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"), - std_string_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string"), - std_string_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string,std::allocator >"), - std_string_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string, std::allocator >"), - std_string_summary_sp); - - // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*) - lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags, - "${var._M_dataplus._M_p%S}")); - - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"), - std_wstring_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string"), - std_wstring_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string,std::allocator >"), - std_wstring_summary_sp); - gnu_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string, std::allocator >"), - std_wstring_summary_sp); + LoadVectorFormatters(); - -#ifndef LLDB_DISABLE_PYTHON - - SyntheticChildren::Flags stl_synth_flags; - stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); - - gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")), - SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); - gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")), - SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); - gnu_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")), - SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, - "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); - - stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true); - gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, - "size=${svar%#}"))); - gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, - "size=${svar%#}"))); - gnu_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, - "size=${svar%#}"))); - - AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); - - AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); -#endif -} - -void -FormatManager::LoadLibcxxFormatters() -{ - TypeSummaryImpl::Flags stl_summary_flags; - stl_summary_flags.SetCascades(true) - .SetSkipPointers(false) - .SetSkipReferences(false) - .SetDontShowChildren(true) - .SetDontShowValue(true) - .SetShowMembersOneLiner(false) - .SetHideItemNames(false); - -#ifndef LLDB_DISABLE_PYTHON - //std::string code(" lldb.formatters.cpp.libcxx.stdstring_SummaryProvider(valobj,internal_dict)"); - //lldb::TypeSummaryImplSP std_string_summary_sp(new ScriptSummaryFormat(stl_summary_flags, "lldb.formatters.cpp.libcxx.stdstring_SummaryProvider",code.c_str())); - - lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider")); - lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider")); - - TypeCategoryImpl::SharedPointer libcxx_category_sp = GetCategory(m_libcxx_category_name); - - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"), - std_string_summary_sp); - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string, std::__1::allocator >"), - std_string_summary_sp); - - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"), - std_wstring_summary_sp); - libcxx_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string, std::__1::allocator >"), - std_wstring_summary_sp); - - SyntheticChildren::Flags stl_synth_flags; - stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); - - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__1::vector >"), stl_synth_flags); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__1::vector >"), stl_synth_flags); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); - - libcxx_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")), - SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, - "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); - - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); - - stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__1::vector >"), stl_synth_flags); - - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__1::vector >"), stl_summary_flags); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__1::vector >"), stl_summary_flags); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); - - stl_summary_flags.SetSkipPointers(true); - - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true); - - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true); - - AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__1::vector >"), stl_summary_flags); - AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true); - - AddFilter(libcxx_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true); -#endif + EnableCategory(m_vectortypes_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); + EnableCategory(m_system_category_name,TypeCategoryMap::Last, lldb::eLanguageTypeObjC_plus_plus); } void FormatManager::LoadSystemFormatters() { - TypeSummaryImpl::Flags string_flags; string_flags.SetCascades(true) .SetSkipPointers(true) @@ -1157,7 +1086,7 @@ FormatManager::LoadSystemFormatters() .SetHideItemNames(false); TypeSummaryImpl::Flags string_array_flags; - string_array_flags.SetCascades(false) + string_array_flags.SetCascades(true) .SetSkipPointers(true) .SetSkipReferences(false) .SetDontShowChildren(true) @@ -1192,31 +1121,6 @@ FormatManager::LoadSystemFormatters() sys_category_sp->GetTypeSummariesContainer()->Add(ConstString("OSType"), ostype_summary); #ifndef LLDB_DISABLE_PYTHON - // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* () - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); - - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags); - - AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags); - AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true); - - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags); - - TypeSummaryImpl::Flags widechar_flags; - widechar_flags.SetDontShowValue(true) - .SetSkipPointers(true) - .SetSkipReferences(false) - .SetCascades(true) - .SetDontShowChildren(true) - .SetHideItemNames(true) - .SetShowMembersOneLiner(false); - - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags); - AddCXXSummary(sys_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags); - - AddCXXSummary(sys_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags); - TypeFormatImpl::Flags fourchar_flags; fourchar_flags.SetCascades(true).SetSkipPointers(true).SetSkipReferences(true); @@ -1225,283 +1129,10 @@ FormatManager::LoadSystemFormatters() } void -FormatManager::LoadObjCFormatters() +FormatManager::LoadVectorFormatters() { - TypeSummaryImpl::Flags objc_flags; - objc_flags.SetCascades(false) - .SetSkipPointers(true) - .SetSkipReferences(true) - .SetDontShowChildren(true) - .SetDontShowValue(true) - .SetShowMembersOneLiner(false) - .SetHideItemNames(false); - - TypeCategoryImpl::SharedPointer objc_category_sp = GetCategory(m_objc_category_name); - TypeCategoryImpl::SharedPointer appkit_category_sp = GetCategory(m_appkit_category_name); - TypeCategoryImpl::SharedPointer corefoundation_category_sp = GetCategory(m_corefoundation_category_name); - TypeCategoryImpl::SharedPointer coregraphics_category_sp = GetCategory(m_coregraphics_category_name); - TypeCategoryImpl::SharedPointer coreservices_category_sp = GetCategory(m_coreservices_category_name); - - lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,"")); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), - ObjC_BOOL_summary); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"), - ObjC_BOOL_summary); - objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"), - ObjC_BOOL_summary); - -#ifndef LLDB_DISABLE_PYTHON - // we need to skip pointers here since we are special casing a SEL* when retrieving its value - objc_flags.SetSkipPointers(true); - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider, "SEL summary provider", ConstString("SEL"), objc_flags); - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider, "SEL summary provider", ConstString("struct objc_selector"), objc_flags); - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider, "SEL summary provider", ConstString("objc_selector"), objc_flags); - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider, "SEL summary provider", ConstString("objc_selector *"), objc_flags); - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider, "SEL summary provider", ConstString("SEL *"), objc_flags); - - AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags); - - SyntheticChildren::Flags class_synth_flags; - class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); - - AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags); -#endif // LLDB_DISABLE_PYTHON - - objc_flags.SetSkipPointers(false); - objc_flags.SetCascades(true); - objc_flags.SetSkipReferences(false); - - AddStringSummary (objc_category_sp, - "${var.__FuncPtr%A}", - ConstString("__block_literal_generic"), - objc_flags); - - AddStringSummary(corefoundation_category_sp, - "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds", - ConstString("CFGregorianUnits"), - objc_flags); - AddStringSummary(corefoundation_category_sp, - "location=${var.location} length=${var.length}", - ConstString("CFRange"), - objc_flags); - - AddStringSummary(appkit_category_sp, - "location=${var.location}, length=${var.length}", - ConstString("NSRange"), - objc_flags); - AddStringSummary(appkit_category_sp, - "(${var.origin}, ${var.size}), ...", - ConstString("NSRectArray"), - objc_flags); - - AddOneLineSummary (appkit_category_sp, - ConstString("NSPoint"), - objc_flags); - AddOneLineSummary (appkit_category_sp, - ConstString("NSSize"), - objc_flags); - AddOneLineSummary (appkit_category_sp, - ConstString("NSRect"), - objc_flags); - - AddOneLineSummary (coregraphics_category_sp, - ConstString("CGSize"), - objc_flags); - AddOneLineSummary (coregraphics_category_sp, - ConstString("CGPoint"), - objc_flags); - AddOneLineSummary (coregraphics_category_sp, - ConstString("CGRect"), - objc_flags); - - AddStringSummary(coreservices_category_sp, - "red=${var.red} green=${var.green} blue=${var.blue}", - ConstString("RGBColor"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", - ConstString("Rect"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "(v=${var.v}, h=${var.h})", - ConstString("Point"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "${var.month}/${var.day}/${var.year} ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}", - ConstString("DateTimeRect *"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}", - ConstString("LongDateRect"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "(x=${var.x}, y=${var.y})", - ConstString("HIPoint"), - objc_flags); - AddStringSummary(coreservices_category_sp, - "origin=${var.origin} size=${var.size}", - ConstString("HIRect"), - objc_flags); - - TypeSummaryImpl::Flags appkit_flags; - appkit_flags.SetCascades(true) - .SetSkipPointers(false) - .SetSkipReferences(false) - .SetDontShowChildren(true) - .SetDontShowValue(false) - .SetShowMembersOneLiner(false) - .SetHideItemNames(false); - - appkit_flags.SetDontShowChildren(false); - - -#ifndef LLDB_DISABLE_PYTHON - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "NSSet summary", ConstString("NSSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSSetSummaryProvider, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSSetSummaryProvider, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags); - - // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags); - - appkit_flags.SetDontShowChildren(true); - - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags()); - - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(corefoundation_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags()); - - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags()); - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags()); - - AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags()); - - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags); - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags); - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags); - - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSData"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSMutableData"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("__NSCFData"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("CFDataRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags); - - AddStringSummary(appkit_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags); - AddStringSummary(appkit_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags); - - // CFAbsoluteTime is actually a double rather than a pointer to an object - // we do not care about the numeric value, since it is probably meaningless to users - appkit_flags.SetDontShowValue(true); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags); - appkit_flags.SetDontShowValue(false); - - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags); - AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags); - - AddStringSummary(corefoundation_category_sp, - "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"", - ConstString("CFGregorianDate"), - appkit_flags); - - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags); - AddCXXSummary(corefoundation_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags); -#endif // LLDB_DISABLE_PYTHON - TypeCategoryImpl::SharedPointer vectors_category_sp = GetCategory(m_vectortypes_category_name); - + TypeSummaryImpl::Flags vector_flags; vector_flags.SetCascades(true) .SetSkipPointers(true) @@ -1514,8 +1145,8 @@ FormatManager::LoadObjCFormatters() AddStringSummary(vectors_category_sp, "${var.uint128}", ConstString("builtin_type_vec128"), - objc_flags); - + vector_flags); + AddStringSummary(vectors_category_sp, "", ConstString("float [4]"), @@ -1569,84 +1200,3 @@ FormatManager::LoadObjCFormatters() ConstString("vBool32"), vector_flags); } - -void -FormatManager::LoadCoreMediaFormatters() -{ - TypeSummaryImpl::Flags cm_flags; - cm_flags.SetCascades(true) - .SetDontShowChildren(false) - .SetDontShowValue(false) - .SetHideItemNames(false) - .SetShowMembersOneLiner(false) - .SetSkipPointers(false) - .SetSkipReferences(false); - - TypeCategoryImpl::SharedPointer cm_category_sp = GetCategory(m_coremedia_category_name); - -#ifndef LLDB_DISABLE_PYTHON - AddCXXSummary(cm_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags); -#endif // LLDB_DISABLE_PYTHON -} - -void -FormatManager::LoadHardcodedFormatters() -{ - { - // insert code to load formats here - } - { - // insert code to load summaries here - m_hardcoded_summaries.push_back( - [](lldb_private::ValueObject& valobj, - lldb::DynamicValueType, - FormatManager&) -> TypeSummaryImpl::SharedPointer { - static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::FunctionPointerSummaryProvider, "Function pointer summary provider")); - if (valobj.GetClangType().IsFunctionPointerType()) - { - return formatter_sp; - } - return nullptr; - }); - m_hardcoded_summaries.push_back( - [](lldb_private::ValueObject& valobj, - lldb::DynamicValueType, - FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer { - static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags() - .SetCascades(true) - .SetDontShowChildren(true) - .SetHideItemNames(true) - .SetShowMembersOneLiner(true) - .SetSkipPointers(true) - .SetSkipReferences(false), - lldb_private::formatters::VectorTypeSummaryProvider, - "vector_type pointer summary provider")); - if (valobj.GetClangType().IsVectorType(nullptr, nullptr)) - { - if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled()) - return formatter_sp; - } - return nullptr; - }); - } - { - // insert code to load synthetics here - m_hardcoded_synthetics.push_back( - [](lldb_private::ValueObject& valobj, - lldb::DynamicValueType, - FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer { - static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true), - "vector_type synthetic children", - lldb_private::formatters::VectorTypeSyntheticFrontEndCreator)); - if (valobj.GetClangType().IsVectorType(nullptr, nullptr)) - { - if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled()) - return formatter_sp; - } - return nullptr; - }); - } - { - // insert code to load validators here - } -} diff --git a/source/DataFormatters/FormattersHelpers.cpp b/source/DataFormatters/FormattersHelpers.cpp new file mode 100644 index 000000000000..4b0e82e975e4 --- /dev/null +++ b/source/DataFormatters/FormattersHelpers.cpp @@ -0,0 +1,336 @@ +//===-- FormattersHelpers.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes + +// C++ Includes + +// Other libraries and framework includes + +// Project includes +#include "lldb/DataFormatters/FormattersHelpers.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +lldb_private::formatters::AddFormat (TypeCategoryImpl::SharedPointer category_sp, + lldb::Format format, + ConstString type_name, + TypeFormatImpl::Flags flags, + bool regex) +{ + lldb::TypeFormatImplSP format_sp(new TypeFormatImpl_Format(format, flags)); + + if (regex) + category_sp->GetRegexTypeFormatsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),format_sp); + else + category_sp->GetTypeFormatsContainer()->Add(type_name, format_sp); +} + +void +lldb_private::formatters::AddSummary(TypeCategoryImpl::SharedPointer category_sp, + TypeSummaryImplSP summary_sp, + ConstString type_name, + bool regex) +{ + if (regex) + category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); + else + category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); +} + +void +lldb_private::formatters::AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, + const char* string, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex) +{ + lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, + string)); + + if (regex) + category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); + else + category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); +} + +void +lldb_private::formatters::AddOneLineSummary (TypeCategoryImpl::SharedPointer category_sp, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex) +{ + flags.SetShowMembersOneLiner(true); + lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, "")); + + if (regex) + category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); + else + category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); +} + +#ifndef LLDB_DISABLE_PYTHON +void +lldb_private::formatters::AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp, + CXXFunctionSummaryFormat::Callback funct, + const char* description, + ConstString type_name, + TypeSummaryImpl::Flags flags, + bool regex) +{ + lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description)); + if (regex) + category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())),summary_sp); + else + category_sp->GetTypeSummariesContainer()->Add(type_name, summary_sp); +} + +void +lldb_private::formatters::AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp, + CXXSyntheticChildren::CreateFrontEndCallback generator, + const char* description, + ConstString type_name, + ScriptedSyntheticChildren::Flags flags, + bool regex) +{ + lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator)); + if (regex) + category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp); + else + category_sp->GetTypeSyntheticsContainer()->Add(type_name,synth_sp); +} + +void +lldb_private::formatters::AddFilter (TypeCategoryImpl::SharedPointer category_sp, + std::vector children, + const char* description, + ConstString type_name, + ScriptedSyntheticChildren::Flags flags, + bool regex) +{ + TypeFilterImplSP filter_sp(new TypeFilterImpl(flags)); + for (auto child : children) + filter_sp->AddExpressionPath(child); + if (regex) + category_sp->GetRegexTypeFiltersContainer()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), filter_sp); + else + category_sp->GetTypeFiltersContainer()->Add(type_name,filter_sp); +} +#endif + +StackFrame* +lldb_private::formatters::GetViableFrame (ExecutionContext exe_ctx) +{ + StackFrame* frame = exe_ctx.GetFramePtr(); + if (frame) + return frame; + + Process* process = exe_ctx.GetProcessPtr(); + if (!process) + return nullptr; + + ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); + if (thread_sp) + return thread_sp->GetSelectedFrame().get(); + return nullptr; +} + +bool +lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + uint64_t &value) +{ + if (!target_type || !*target_type) + return false; + if (!selector || !*selector) + return false; + StreamString expr; + expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + lldb::ValueObjectSP result_sp; + Target* target = exe_ctx.GetTargetPtr(); + StackFrame* stack_frame = GetViableFrame(exe_ctx); + if (!target || !stack_frame) + return false; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(true); + options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); + options.SetResultIsInternal(true); + options.SetUseDynamic(lldb::eDynamicCanRunTarget); + + target->EvaluateExpression(expr.GetData(), + stack_frame, + result_sp, + options); + if (!result_sp) + return false; + value = result_sp->GetValueAsUnsigned(0); + return true; +} + +bool +lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + Stream &stream, + lldb::LanguageType lang_type) +{ + if (!target_type || !*target_type) + return false; + if (!selector || !*selector) + return false; + StreamString expr; + expr.Printf("(%s)[(id)0x%" PRIx64 " %s]",target_type,valobj.GetPointerValue(),selector); + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + lldb::ValueObjectSP result_sp; + Target* target = exe_ctx.GetTargetPtr(); + StackFrame* stack_frame = GetViableFrame(exe_ctx); + if (!target || !stack_frame) + return false; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(true); + options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); + options.SetResultIsInternal(true); + options.SetUseDynamic(lldb::eDynamicCanRunTarget); + + target->EvaluateExpression(expr.GetData(), + stack_frame, + result_sp, + options); + if (!result_sp) + return false; + stream.Printf("%s",result_sp->GetSummaryAsCString(lang_type)); + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + uint64_t index) +{ + lldb::ValueObjectSP valobj_sp; + if (!return_type || !*return_type) + return valobj_sp; + if (!selector || !*selector) + return valobj_sp; + StreamString expr; + const char *colon = ""; + llvm::StringRef selector_sr(selector); + if (selector_sr.back() != ':') + colon = ":"; + expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%" PRId64 "]",return_type,valobj.GetPointerValue(),selector,colon,index); + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + lldb::ValueObjectSP result_sp; + Target* target = exe_ctx.GetTargetPtr(); + StackFrame* stack_frame = GetViableFrame(exe_ctx); + if (!target || !stack_frame) + return valobj_sp; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(true); + options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); + options.SetResultIsInternal(true); + options.SetUseDynamic(lldb::eDynamicCanRunTarget); + + target->EvaluateExpression(expr.GetData(), + stack_frame, + valobj_sp, + options); + return valobj_sp; +} + +lldb::ValueObjectSP +lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + const char* key) +{ + lldb::ValueObjectSP valobj_sp; + if (!return_type || !*return_type) + return valobj_sp; + if (!selector || !*selector) + return valobj_sp; + if (!key || !*key) + return valobj_sp; + StreamString expr; + const char *colon = ""; + llvm::StringRef selector_sr(selector); + if (selector_sr.back() != ':') + colon = ":"; + expr.Printf("(%s)[(id)0x%" PRIx64 " %s%s%s]",return_type,valobj.GetPointerValue(),selector,colon,key); + ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); + lldb::ValueObjectSP result_sp; + Target* target = exe_ctx.GetTargetPtr(); + StackFrame* stack_frame = GetViableFrame(exe_ctx); + if (!target || !stack_frame) + return valobj_sp; + + EvaluateExpressionOptions options; + options.SetCoerceToId(false); + options.SetUnwindOnError(true); + options.SetKeepInMemory(true); + options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); + options.SetResultIsInternal(true); + options.SetUseDynamic(lldb::eDynamicCanRunTarget); + + target->EvaluateExpression(expr.GetData(), + stack_frame, + valobj_sp, + options); + return valobj_sp; +} + +size_t +lldb_private::formatters::ExtractIndexFromString (const char* item_name) +{ + if (!item_name || !*item_name) + return UINT32_MAX; + if (*item_name != '[') + return UINT32_MAX; + item_name++; + char* endptr = NULL; + unsigned long int idx = ::strtoul(item_name, &endptr, 0); + if (idx == 0 && endptr == item_name) + return UINT32_MAX; + if (idx == ULONG_MAX) + return UINT32_MAX; + return idx; +} + +lldb::addr_t +lldb_private::formatters::GetArrayAddressOrPointerValue (ValueObject& valobj) +{ + lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; + + if (valobj.IsPointerType()) + data_addr = valobj.GetValueAsUnsigned(0); + else if (valobj.IsArrayType()) + data_addr = valobj.GetAddressOf(); + + return data_addr; +} diff --git a/source/DataFormatters/LanguageCategory.cpp b/source/DataFormatters/LanguageCategory.cpp new file mode 100644 index 000000000000..261c3e6302e1 --- /dev/null +++ b/source/DataFormatters/LanguageCategory.cpp @@ -0,0 +1,271 @@ +//===-- LanguageCategory.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/DataFormatters/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" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/DataFormatters/TypeValidator.h" +#include "lldb/Target/Language.h" + +using namespace lldb; +using namespace lldb_private; + +LanguageCategory::LanguageCategory (lldb::LanguageType lang_type) : + m_category_sp(), + m_hardcoded_formats(), + m_hardcoded_summaries(), + m_hardcoded_synthetics(), + m_hardcoded_validators(), + m_format_cache(), + m_enabled(false) +{ + if (Language* language_plugin = Language::FindPlugin(lang_type)) + { + m_category_sp = language_plugin->GetFormatters(); + m_hardcoded_formats = language_plugin->GetHardcodedFormats(); + m_hardcoded_summaries = language_plugin->GetHardcodedSummaries(); + m_hardcoded_synthetics = language_plugin->GetHardcodedSynthetics(); + m_hardcoded_validators = language_plugin->GetHardcodedValidators(); + } + Enable(); +} + +bool +LanguageCategory::Get (FormattersMatchData& match_data, + lldb::TypeFormatImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + if (!IsEnabled()) + return false; + + if (match_data.GetTypeForCache()) + { + if (m_format_cache.GetFormat(match_data.GetTypeForCache(), format_sp)) + return format_sp.get() != nullptr; + } + + ValueObject& valobj(match_data.GetValueObject()); + bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp); + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp); + } + return result; +} + +bool +LanguageCategory::Get (FormattersMatchData& match_data, + lldb::TypeSummaryImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + if (!IsEnabled()) + return false; + + if (match_data.GetTypeForCache()) + { + if (m_format_cache.GetSummary(match_data.GetTypeForCache(), format_sp)) + return format_sp.get() != nullptr; + } + + ValueObject& valobj(match_data.GetValueObject()); + bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp); + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp); + } + return result; +} + +bool +LanguageCategory::Get (FormattersMatchData& match_data, + lldb::SyntheticChildrenSP& format_sp) +{ + if (!m_category_sp) + return false; + + if (!IsEnabled()) + return false; + + if (match_data.GetTypeForCache()) + { + if (m_format_cache.GetSynthetic(match_data.GetTypeForCache(), format_sp)) + return format_sp.get() != nullptr; + } + + ValueObject& valobj(match_data.GetValueObject()); + bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp); + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp); + } + return result; +} + +bool +LanguageCategory::Get (FormattersMatchData& match_data, + lldb::TypeValidatorImplSP& format_sp) +{ + if (!m_category_sp) + return false; + + if (!IsEnabled()) + return false; + + if (match_data.GetTypeForCache()) + { + if (m_format_cache.GetValidator(match_data.GetTypeForCache(), format_sp)) + return format_sp.get() != nullptr; + } + + ValueObject& valobj(match_data.GetValueObject()); + bool result = m_category_sp->Get(valobj, match_data.GetMatchesVector(), format_sp); + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp); + } + return result; +} + +bool +LanguageCategory::GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeFormatImplSP& format_sp) +{ + if (!IsEnabled()) + return false; + + ValueObject& valobj(match_data.GetValueObject()); + lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType()); + + for (auto& candidate : m_hardcoded_formats) + { + if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr))) + break; + } + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetFormat(match_data.GetTypeForCache(), format_sp); + } + return format_sp.get() != nullptr; +} + +bool +LanguageCategory::GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeSummaryImplSP& format_sp) +{ + if (!IsEnabled()) + return false; + + ValueObject& valobj(match_data.GetValueObject()); + lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType()); + + for (auto& candidate : m_hardcoded_summaries) + { + if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr))) + break; + } + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSummary(match_data.GetTypeForCache(), format_sp); + } + return format_sp.get() != nullptr; +} + +bool +LanguageCategory::GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::SyntheticChildrenSP& format_sp) +{ + if (!IsEnabled()) + return false; + + ValueObject& valobj(match_data.GetValueObject()); + lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType()); + + for (auto& candidate : m_hardcoded_synthetics) + { + if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr))) + break; + } + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetSynthetic(match_data.GetTypeForCache(), format_sp); + } + return format_sp.get() != nullptr; +} + +bool +LanguageCategory::GetHardcoded (FormatManager& fmt_mgr, + FormattersMatchData& match_data, + lldb::TypeValidatorImplSP& format_sp) +{ + if (!IsEnabled()) + return false; + + ValueObject& valobj(match_data.GetValueObject()); + lldb::DynamicValueType use_dynamic(match_data.GetDynamicValueType()); + + for (auto& candidate : m_hardcoded_validators) + { + if ((format_sp = candidate(valobj, use_dynamic, fmt_mgr))) + break; + } + if (match_data.GetTypeForCache() && (!format_sp || !format_sp->NonCacheable())) + { + m_format_cache.SetValidator(match_data.GetTypeForCache(), format_sp); + } + return format_sp.get() != nullptr; +} + +lldb::TypeCategoryImplSP +LanguageCategory::GetCategory () const +{ + return m_category_sp; +} + +FormatCache& +LanguageCategory::GetFormatCache () +{ + return m_format_cache; +} + +void +LanguageCategory::Enable () +{ + if (m_category_sp) + m_category_sp->Enable(true, TypeCategoryMap::Default); + m_enabled = true; +} + +void +LanguageCategory::Disable () +{ + if (m_category_sp) + m_category_sp->Disable(); + m_enabled = false; +} + +bool +LanguageCategory::IsEnabled () +{ + return m_enabled; +} diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp deleted file mode 100644 index a04b4ff6b8c7..000000000000 --- a/source/DataFormatters/LibCxx.cpp +++ /dev/null @@ -1,463 +0,0 @@ -//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/FormatEntity.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -bool -lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); - if (!valobj_sp) - return false; - ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)); - ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} )); - ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} )); - - if (!ptr_sp) - return false; - - if (ptr_sp->GetValueAsUnsigned(0) == 0) - { - stream.Printf("nullptr"); - return true; - } - else - { - bool print_pointee = false; - Error error; - ValueObjectSP pointee_sp = ptr_sp->Dereference(error); - if (pointee_sp && error.Success()) - { - if (pointee_sp->DumpPrintableRepresentation(stream, - ValueObject::eValueObjectRepresentationStyleSummary, - lldb::eFormatInvalid, - ValueObject::ePrintableRepresentationSpecialCasesDisable, - false)) - print_pointee = true; - } - if (!print_pointee) - stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); - } - - if (count_sp) - stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0)); - - if (weakcount_sp) - stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0)); - - return true; -} - -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_bool_type(), -m_exe_ctx_ref(), -m_count(0), -m_base_data_address(0), -m_children() -{ - if (valobj_sp) - { - Update(); - m_bool_type = valobj_sp->GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeBool); - } -} - -size_t -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () -{ - return m_count; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - auto iter = m_children.find(idx), - end = m_children.end(); - if (iter != end) - return iter->second; - if (idx >= m_count) - return ValueObjectSP(); - if (m_base_data_address == 0 || m_count == 0) - return ValueObjectSP(); - if (!m_bool_type) - return ValueObjectSP(); - 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(); - uint8_t byte = 0; - uint8_t mask = 0; - Error err; - size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); - if (err.Fail() || bytes_read == 0) - return ValueObjectSP(); - switch (bit_index) - { - case 0: - mask = 1; break; - case 1: - mask = 2; break; - case 2: - mask = 4; break; - case 3: - mask = 8; break; - case 4: - mask = 16; break; - case 5: - mask = 32; break; - case 6: - mask = 64; break; - case 7: - mask = 128; break; - default: - return ValueObjectSP(); - } - bool bit_set = ((byte & mask) != 0); - DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0)); - if (bit_set && buffer_sp && buffer_sp->GetBytes()) - *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true - StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type)); - if (retval_sp) - m_children[idx] = retval_sp; - return retval_sp; -} - -/*(std::__1::vector >) vBool = { - __begin_ = 0x00000001001000e0 - __size_ = 56 - __cap_alloc_ = { - std::__1::__libcpp_compressed_pair_imp > = { - __first_ = 1 - } - } - }*/ - -bool -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() -{ - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); - if (!size_sp) - return false; - m_count = size_sp->GetValueAsUnsigned(0); - if (!m_count) - return true; - ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); - if (!begin_sp) - { - m_count = 0; - return false; - } - m_base_data_address = begin_sp->GetValueAsUnsigned(0); - if (!m_base_data_address) - { - m_count = 0; - return false; - } - return false; -} - -bool -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_count || !m_base_data_address) - return UINT32_MAX; - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); -} - -/* - (lldb) fr var ibeg --raw --ptr-depth 1 - (std::__1::__map_iterator, std::__1::allocator > >, std::__1::__tree_node, std::__1::allocator > >, void *> *, long> >) ibeg = { - __i_ = { - __ptr_ = 0x0000000100103870 { - std::__1::__tree_node_base = { - std::__1::__tree_end_node *> = { - __left_ = 0x0000000000000000 - } - __right_ = 0x0000000000000000 - __parent_ = 0x00000001001038b0 - __is_black_ = true - } - __value_ = { - first = 0 - second = { std::string } - */ - -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_pair_ptr() -{ - if (valobj_sp) - Update(); -} - -bool -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() -{ - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - - TargetSP target_sp(valobj_sp->GetTargetSP()); - - if (!target_sp) - return false; - - if (!valobj_sp) - return false; - - // 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 that would in turn leak memory by never allowing the ValueObjects to die and free their memory - m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_", - NULL, - NULL, - NULL, - ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None), - NULL).get(); - - return false; -} - -size_t -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren () -{ - return 2; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (!m_pair_ptr) - return lldb::ValueObjectSP(); - return m_pair_ptr->GetChildAtIndex(idx, true); -} - -bool -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (name == ConstString("first")) - return 0; - if (name == ConstString("second")) - return 1; - return UINT32_MAX; -} - -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd () -{ - // this will be deleted when its parent dies (since it's a child object) - //delete m_pair_ptr; -} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); -} - -/* - (lldb) fr var ibeg --raw --ptr-depth 1 -T - (std::__1::__wrap_iter) ibeg = { - (std::__1::__wrap_iter::iterator_type) __i = 0x00000001001037a0 { - (int) *__i = 1 - } - } -*/ - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - static ConstString g_item_name; - if (!g_item_name) - g_item_name.SetCString("__i"); - if (!valobj_sp) - return NULL; - return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); -} - -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_cntrl(NULL), -m_count_sp(), -m_weak_count_sp(), -m_ptr_size(0), -m_byte_order(lldb::eByteOrderInvalid) -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren () -{ - return (m_cntrl ? 1 : 0); -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (!m_cntrl) - return lldb::ValueObjectSP(); - - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return lldb::ValueObjectSP(); - - if (idx == 0) - return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); - - if (idx > 2) - return lldb::ValueObjectSP(); - - if (idx == 1) - { - if (!m_count_sp) - { - ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true)); - if (!shared_owners_sp) - return lldb::ValueObjectSP(); - uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); - DataExtractor data(&count, 8, m_byte_order, m_ptr_size); - m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType()); - } - return m_count_sp; - } - else /* if (idx == 2) */ - { - if (!m_weak_count_sp) - { - ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true)); - if (!shared_weak_owners_sp) - return lldb::ValueObjectSP(); - uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); - DataExtractor data(&count, 8, m_byte_order, m_ptr_size); - m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType()); - } - return m_weak_count_sp; - } -} - -bool -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() -{ - m_count_sp.reset(); - m_weak_count_sp.reset(); - m_cntrl = NULL; - - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - - TargetSP target_sp(valobj_sp->GetTargetSP()); - if (!target_sp) - return false; - - m_byte_order = target_sp->GetArchitecture().GetByteOrder(); - m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); - - lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true)); - - m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency - return false; -} - -bool -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (name == ConstString("__ptr_")) - return 0; - if (name == ConstString("count")) - return 1; - if (name == ConstString("weak_count")) - return 2; - return UINT32_MAX; -} - -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); -} - -bool -lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - if (valobj.IsPointerType()) - { - uint64_t value = valobj.GetValueAsUnsigned(0); - if (!value) - return false; - stream.Printf("0x%016" PRIx64 " ", value); - } - return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false); -} diff --git a/source/DataFormatters/LibCxxInitializerList.cpp b/source/DataFormatters/LibCxxInitializerList.cpp deleted file mode 100644 index 0dcef981e5e5..000000000000 --- a/source/DataFormatters/LibCxxInitializerList.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===-- LibCxxInitializerList.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/ConstString.h" -#include "lldb/Core/ValueObject.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxInitializerListSyntheticFrontEnd (); - private: - ValueObject* m_start; - ClangASTType m_element_type; - uint32_t m_element_size; - size_t m_num_elements; - std::map m_children; - }; - } -} - -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_start(NULL), -m_element_type(), -m_element_size(0), -m_num_elements(0), -m_children() -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren () -{ - static ConstString g___size_("__size_"); - m_num_elements = 0; - ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true)); - if (size_sp) - m_num_elements = size_sp->GetValueAsUnsigned(0); - return m_num_elements; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (!m_start) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - uint64_t offset = idx * m_element_size; - offset = offset + m_start->GetValueAsUnsigned(0); - StreamString name; - name.Printf("[%" PRIu64 "]", (uint64_t)idx); - ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); - m_children[idx] = child_sp; - return child_sp; -} - -bool -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() -{ - static ConstString g___begin_("__begin_"); - - m_start = nullptr; - m_num_elements = 0; - m_children.clear(); - lldb::TemplateArgumentKind kind; - m_element_type = m_backend.GetClangType().GetTemplateArgument(0, kind); - if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) - return false; - - m_element_size = m_element_type.GetByteSize(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 - - return false; -} - -bool -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_start) - return UINT32_MAX; - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd () -{ - // this needs to stay around because it's a child object who will follow its parent's life cycle - // delete m_start; -} - -lldb_private::SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)); -} - diff --git a/source/DataFormatters/LibCxxList.cpp b/source/DataFormatters/LibCxxList.cpp deleted file mode 100644 index f3e07fe7a017..000000000000 --- a/source/DataFormatters/LibCxxList.cpp +++ /dev/null @@ -1,369 +0,0 @@ -//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdListSyntheticFrontEnd (); - private: - bool - HasLoop(size_t); - - size_t m_list_capping_size; - static const bool g_use_loop_detect = true; - size_t m_loop_detected; - lldb::addr_t m_node_address; - ValueObject* m_head; - ValueObject* m_tail; - ClangASTType m_element_type; - size_t m_count; - std::map m_children; - }; - } -} - -class ListEntry -{ -public: - ListEntry () {} - ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} - ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} - ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} - - ListEntry - next () - { - if (!m_entry_sp) - return ListEntry(); - return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true)); - } - - ListEntry - prev () - { - if (!m_entry_sp) - return ListEntry(); - return ListEntry(m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true)); - } - - uint64_t - value () - { - if (!m_entry_sp) - return 0; - return m_entry_sp->GetValueAsUnsigned(0); - } - - bool - null() - { - return (value() == 0); - } - - explicit operator bool () - { - return GetEntry().get() != nullptr && null() == false; - } - - ValueObjectSP - GetEntry () - { - return m_entry_sp; - } - - void - SetEntry (ValueObjectSP entry) - { - m_entry_sp = entry; - } - - bool - operator == (const ListEntry& rhs) const - { - return (rhs.m_entry_sp.get() == m_entry_sp.get()); - } - -private: - ValueObjectSP m_entry_sp; -}; - -class ListIterator -{ -public: - ListIterator () {} - ListIterator (ListEntry entry) : m_entry(entry) {} - ListIterator (ValueObjectSP entry) : m_entry(entry) {} - ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {} - ListIterator (ValueObject* entry) : m_entry(entry) {} - - ValueObjectSP - value () - { - return m_entry.GetEntry(); - } - - ValueObjectSP - advance (size_t count) - { - if (count == 0) - return m_entry.GetEntry(); - if (count == 1) - { - next (); - return m_entry.GetEntry(); - } - while (count > 0) - { - next (); - count--; - if (m_entry.null()) - return lldb::ValueObjectSP(); - } - return m_entry.GetEntry(); - } - - bool - operator == (const ListIterator& rhs) const - { - return (rhs.m_entry == m_entry); - } - -protected: - void - next () - { - m_entry = m_entry.next(); - } - - void - prev () - { - m_entry = m_entry.prev(); - } -private: - ListEntry m_entry; -}; - -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_list_capping_size(0), -m_loop_detected(0), -m_node_address(), -m_head(NULL), -m_tail(NULL), -m_element_type(), -m_count(UINT32_MAX), -m_children() -{ - if (valobj_sp) - Update(); -} - -bool -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count) -{ - if (g_use_loop_detect == false) - return false; - // don't bother checking for a loop if we won't actually need to jump nodes - if (m_count < 2) - return false; - auto steps_left = std::min(count,m_count); - auto steps_left_save = steps_left; - ListEntry slow(m_head); - ListEntry fast(m_head); - while (steps_left-- > 0) - { - slow = slow.next(); - fast = fast.next(); - if (fast.next()) - fast = fast.next().next(); - else - fast = nullptr; - if (!slow || !fast) - return false; - if (slow == fast) - return true; - } - m_loop_detected = steps_left_save; - return false; -} - -size_t -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren () -{ - if (m_count != UINT32_MAX) - return m_count; - if (!m_head || !m_tail || m_node_address == 0) - return 0; - ValueObjectSP size_alloc(m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true)); - if (size_alloc) - { - ValueObjectSP first(size_alloc->GetChildMemberWithName(ConstString("__first_"), true)); - if (first) - { - m_count = first->GetValueAsUnsigned(UINT32_MAX); - } - } - if (m_count != UINT32_MAX) - { - return m_count; - } - else - { - uint64_t next_val = m_head->GetValueAsUnsigned(0); - uint64_t prev_val = m_tail->GetValueAsUnsigned(0); - if (next_val == 0 || prev_val == 0) - return 0; - if (next_val == m_node_address) - return 0; - if (next_val == prev_val) - return 1; - uint64_t size = 2; - ListEntry current(m_head); - while (current.next() && current.next().value() != m_node_address) - { - size++; - current = current.next(); - if (size > m_list_capping_size) - break; - } - return m_count = (size-1); - } -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - - if (!m_head || !m_tail || m_node_address == 0) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - if (m_loop_detected <= idx) - if (HasLoop(idx)) - return lldb::ValueObjectSP(); - - ListIterator current(m_head); - ValueObjectSP current_sp(current.advance(idx)); - if (!current_sp) - return lldb::ValueObjectSP(); - current_sp = current_sp->GetChildMemberWithName(ConstString("__value_"), true); - if (!current_sp) - return lldb::ValueObjectSP(); - // we need to copy current_sp into a new object otherwise we will end up with all items named __value_ - DataExtractor data; - Error error; - current_sp->GetData(data, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - - StreamString name; - name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); -} - -bool -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() -{ - m_head = m_tail = NULL; - m_node_address = 0; - m_count = UINT32_MAX; - m_loop_detected = false; - Error err; - ValueObjectSP backend_addr(m_backend.AddressOf(err)); - m_list_capping_size = 0; - if (m_backend.GetTargetSP()) - m_list_capping_size = m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - if (m_list_capping_size == 0) - m_list_capping_size = 255; - if (err.Fail() || backend_addr.get() == NULL) - return false; - m_node_address = backend_addr->GetValueAsUnsigned(0); - if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS) - return false; - ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true)); - if (!impl_sp) - return false; - ClangASTType list_type = m_backend.GetClangType(); - if (list_type.IsReferenceType()) - list_type = list_type.GetNonReferenceType(); - - if (list_type.GetNumTemplateArguments() == 0) - return false; - lldb::TemplateArgumentKind kind; - m_element_type = list_type.GetTemplateArgument(0, kind); - m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); - m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); - return false; -} - -bool -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::~LibcxxStdListSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxStdListSyntheticFrontEnd(valobj_sp)); -} - diff --git a/source/DataFormatters/LibCxxMap.cpp b/source/DataFormatters/LibCxxMap.cpp deleted file mode 100644 index 2ff623284845..000000000000 --- a/source/DataFormatters/LibCxxMap.cpp +++ /dev/null @@ -1,452 +0,0 @@ -//===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdMapSyntheticFrontEnd (); - private: - bool - GetDataType(); - - void - GetValueOffset (const lldb::ValueObjectSP& node); - - ValueObject* m_tree; - ValueObject* m_root_node; - ClangASTType m_element_type; - uint32_t m_skip_size; - size_t m_count; - std::map m_children; - }; - } -} - -class MapEntry -{ -public: - MapEntry () {} - explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} - MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} - explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} - - ValueObjectSP - left () const - { - static ConstString g_left("__left_"); - if (!m_entry_sp) - return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(g_left, true); - } - - ValueObjectSP - right () const - { - static ConstString g_right("__right_"); - if (!m_entry_sp) - return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(g_right, true); - } - - ValueObjectSP - parent () const - { - static ConstString g_parent("__parent_"); - if (!m_entry_sp) - return m_entry_sp; - return m_entry_sp->GetChildMemberWithName(g_parent, true); - } - - uint64_t - value () const - { - if (!m_entry_sp) - return 0; - return m_entry_sp->GetValueAsUnsigned(0); - } - - bool - error () const - { - if (!m_entry_sp) - return true; - return m_entry_sp->GetError().Fail(); - } - - bool - null() const - { - return (value() == 0); - } - - ValueObjectSP - GetEntry () const - { - return m_entry_sp; - } - - void - SetEntry (ValueObjectSP entry) - { - m_entry_sp = entry; - } - - bool - operator == (const MapEntry& rhs) const - { - return (rhs.m_entry_sp.get() == m_entry_sp.get()); - } - -private: - ValueObjectSP m_entry_sp; -}; - -class MapIterator -{ -public: - MapIterator () {} - MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} - MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} - MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {} - MapIterator (ValueObject* entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} - - ValueObjectSP - value () - { - return m_entry.GetEntry(); - } - - ValueObjectSP - advance (size_t count) - { - ValueObjectSP fail(nullptr); - if (m_error) - return fail; - size_t steps = 0; - while (count > 0) - { - next(); - count--, steps++; - if (m_error || - m_entry.null() || - (steps > m_max_depth)) - return fail; - } - return m_entry.GetEntry(); - } -protected: - void - next () - { - if (m_entry.null()) - return; - MapEntry right(m_entry.right()); - if (right.null() == false) - { - m_entry = tree_min(std::move(right)); - return; - } - size_t steps = 0; - while (!is_left_child(m_entry)) - { - if (m_entry.error()) - { - m_error = true; - return; - } - m_entry.SetEntry(m_entry.parent()); - steps++; - if (steps > m_max_depth) - { - m_entry = MapEntry(); - return; - } - } - m_entry = MapEntry(m_entry.parent()); - } - -private: - MapEntry - tree_min (MapEntry&& x) - { - if (x.null()) - return MapEntry(); - MapEntry left(x.left()); - size_t steps = 0; - while (left.null() == false) - { - if (left.error()) - { - m_error = true; - return MapEntry(); - } - x = left; - left.SetEntry(x.left()); - steps++; - if (steps > m_max_depth) - return MapEntry(); - } - return x; - } - - bool - is_left_child (const MapEntry& x) - { - if (x.null()) - return false; - MapEntry rhs(x.parent()); - rhs.SetEntry(rhs.left()); - return x.value() == rhs.value(); - } - - MapEntry m_entry; - size_t m_max_depth; - bool m_error; -}; - -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_tree(NULL), -m_root_node(NULL), -m_element_type(), -m_skip_size(UINT32_MAX), -m_count(UINT32_MAX), -m_children() -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren () -{ - if (m_count != UINT32_MAX) - return m_count; - if (m_tree == NULL) - return 0; - ValueObjectSP m_item(m_tree->GetChildMemberWithName(ConstString("__pair3_"), true)); - if (!m_item) - return 0; - m_item = m_item->GetChildMemberWithName(ConstString("__first_"), true); - if (!m_item) - return 0; - m_count = m_item->GetValueAsUnsigned(0); - return m_count; -} - -bool -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() -{ - if (m_element_type.GetOpaqueQualType() && m_element_type.GetASTContext()) - return true; - m_element_type.Clear(); - ValueObjectSP deref; - Error error; - deref = m_root_node->Dereference(error); - if (!deref || error.Fail()) - return false; - deref = deref->GetChildMemberWithName(ConstString("__value_"), true); - if (!deref) - return false; - m_element_type = deref->GetClangType(); - return true; -} - -void -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const lldb::ValueObjectSP& node) -{ - if (m_skip_size != UINT32_MAX) - return; - if (!node) - return; - ClangASTType node_type(node->GetClangType()); - uint64_t bit_offset; - if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX) - return; - m_skip_size = bit_offset / 8u; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - static ConstString g___cc("__cc"); - static ConstString g___nc("__nc"); - - - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - if (m_tree == NULL || m_root_node == NULL) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - bool need_to_skip = (idx > 0); - MapIterator iterator(m_root_node, CalculateNumChildren()); - ValueObjectSP iterated_sp(iterator.advance(idx)); - if (iterated_sp.get() == NULL) - { - // this tree is garbage - stop - m_tree = NULL; // this will stop all future searches until an Update() happens - return iterated_sp; - } - if (GetDataType()) - { - if (!need_to_skip) - { - Error error; - iterated_sp = iterated_sp->Dereference(error); - if (!iterated_sp || error.Fail()) - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - GetValueOffset(iterated_sp); - iterated_sp = iterated_sp->GetChildMemberWithName(ConstString("__value_"), true); - if (!iterated_sp) - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - } - else - { - // because of the way our debug info is made, we need to read item 0 first - // so that we can cache information used to generate other elements - if (m_skip_size == UINT32_MAX) - GetChildAtIndex(0); - if (m_skip_size == UINT32_MAX) - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true); - if (!iterated_sp) - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - } - } - else - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - // at this point we have a valid - // we need to copy current_sp into a new object otherwise we will end up with all items named __value_ - DataExtractor data; - Error error; - iterated_sp->GetData(data, error); - if (error.Fail()) - { - m_tree = NULL; - return lldb::ValueObjectSP(); - } - StreamString name; - name.Printf("[%" PRIu64 "]", (uint64_t)idx); - auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type); - if (potential_child_sp) - { - switch (potential_child_sp->GetNumChildren()) - { - case 1: - { - auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); - if (child0_sp && child0_sp->GetName() == g___cc) - potential_child_sp = child0_sp; - break; - } - case 2: - { - auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); - auto child1_sp = potential_child_sp->GetChildAtIndex(1, true); - if (child0_sp && child0_sp->GetName() == g___cc && - child1_sp && child1_sp->GetName() == g___nc) - potential_child_sp = child0_sp; - break; - } - } - potential_child_sp->SetName(ConstString(name.GetData())); - } - return (m_children[idx] = potential_child_sp); -} - -bool -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() -{ - m_count = UINT32_MAX; - m_tree = m_root_node = NULL; - m_children.clear(); - m_tree = m_backend.GetChildMemberWithName(ConstString("__tree_"), true).get(); - if (!m_tree) - return false; - m_root_node = m_tree->GetChildMemberWithName(ConstString("__begin_node_"), true).get(); - return false; -} - -bool -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::~LibcxxStdMapSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp)); -} diff --git a/source/DataFormatters/LibCxxUnorderedMap.cpp b/source/DataFormatters/LibCxxUnorderedMap.cpp deleted file mode 100644 index 43669803195e..000000000000 --- a/source/DataFormatters/LibCxxUnorderedMap.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//===-- LibCxxUnorderedMap.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdUnorderedMapSyntheticFrontEnd (); - private: - - ValueObject* m_tree; - size_t m_num_elements; - ValueObject* m_next_element; - std::map m_children; - std::vector > m_elements_cache; - }; - } -} - -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_tree(NULL), -m_num_elements(0), -m_next_element(nullptr), -m_children(), -m_elements_cache() -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren () -{ - if (m_num_elements != UINT32_MAX) - return m_num_elements; - return 0; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - if (m_tree == NULL) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - while (idx >= m_elements_cache.size()) - { - if (m_next_element == nullptr) - return lldb::ValueObjectSP(); - - Error error; - ValueObjectSP node_sp = m_next_element->Dereference(error); - if (!node_sp || error.Fail()) - return lldb::ValueObjectSP(); - - ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true); - ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true); - if (!hash_sp || !value_sp) - return lldb::ValueObjectSP(); - m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)}); - m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get(); - if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0) - m_next_element = nullptr; - } - - std::pair val_hash = m_elements_cache[idx]; - if (!val_hash.first) - return lldb::ValueObjectSP(); - StreamString stream; - stream.Printf("[%" PRIu64 "]", (uint64_t)idx); - DataExtractor data; - Error error; - val_hash.first->GetData(data, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - const bool thread_and_frame_only_if_stopped = true; - ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped); - return val_hash.first->CreateValueObjectFromData(stream.GetData(), - data, - exe_ctx, - val_hash.first->GetClangType()); -} - -bool -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update() -{ - m_num_elements = UINT32_MAX; - m_next_element = nullptr; - m_elements_cache.clear(); - m_children.clear(); - ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true); - if (!table_sp) - return false; - ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")}); - if (!num_elements_sp) - return false; - m_num_elements = num_elements_sp->GetValueAsUnsigned(0); - m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get(); - if (m_num_elements > 0) - m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get(); - return false; -} - -bool -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)); -} diff --git a/source/DataFormatters/LibCxxVector.cpp b/source/DataFormatters/LibCxxVector.cpp deleted file mode 100644 index 6ccb732f6779..000000000000 --- a/source/DataFormatters/LibCxxVector.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/ConstString.h" -#include "lldb/Core/ValueObject.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibcxxStdVectorSyntheticFrontEnd (); - private: - ValueObject* m_start; - ValueObject* m_finish; - ClangASTType m_element_type; - uint32_t m_element_size; - std::map m_children; - }; - } -} - -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_start(NULL), -m_finish(NULL), -m_element_type(), -m_element_size(0), -m_children() -{ - if (valobj_sp) - Update(); -} - -size_t -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_start || !m_finish) - return 0; - uint64_t start_val = m_start->GetValueAsUnsigned(0); - uint64_t finish_val = m_finish->GetValueAsUnsigned(0); - - if (start_val == 0 || finish_val == 0) - return 0; - - if (start_val >= finish_val) - return 0; - - size_t num_children = (finish_val - start_val); - if (num_children % m_element_size) - return 0; - return num_children/m_element_size; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (!m_start || !m_finish) - return lldb::ValueObjectSP(); - - auto cached = m_children.find(idx); - if (cached != m_children.end()) - return cached->second; - - uint64_t offset = idx * m_element_size; - offset = offset + m_start->GetValueAsUnsigned(0); - StreamString name; - name.Printf("[%" PRIu64 "]", (uint64_t)idx); - ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); - m_children[idx] = child_sp; - return child_sp; -} - -bool -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() -{ - m_start = m_finish = NULL; - m_children.clear(); - ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); - if (!data_type_finder_sp) - return false; - data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); - if (!data_type_finder_sp) - return false; - m_element_type = data_type_finder_sp->GetClangType().GetPointeeType(); - m_element_size = m_element_type.GetByteSize(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(); - } - return false; -} - -bool -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_start || !m_finish) - return UINT32_MAX; - return ExtractIndexFromString(name.GetCString()); -} - -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () -{ - // these need to stay around because they are child objects who will follow their parent's life cycle - // delete m_start; - // delete m_finish; -} - -lldb_private::SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); -} - diff --git a/source/DataFormatters/LibStdcpp.cpp b/source/DataFormatters/LibStdcpp.cpp deleted file mode 100644 index 2b3bcb58afac..000000000000 --- a/source/DataFormatters/LibStdcpp.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -/* - (std::_Rb_tree_iterator, std::allocator > > >) ibeg = { - (_Base_ptr) _M_node = 0x0000000100103910 { - (std::_Rb_tree_color) _M_color = _S_black - (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 - (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 - (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 - } - } - */ - -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()), - m_exe_ctx_ref(), - m_pair_address(0), - m_pair_type(), - m_options(), - m_pair_sp() -{ - if (valobj_sp) - Update(); - m_options.SetCoerceToId(false); - m_options.SetUnwindOnError(true); - m_options.SetKeepInMemory(true); - m_options.SetUseDynamic(lldb::eDynamicCanRunTarget); -} - -bool -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::Update() -{ - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - - TargetSP target_sp(valobj_sp->GetTargetSP()); - - if (!target_sp) - return false; - - bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8); - - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - - ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true)); - if (!_M_node_sp) - return false; - - m_pair_address = _M_node_sp->GetValueAsUnsigned(0); - if (m_pair_address == 0) - return false; - - m_pair_address += (is_64bit ? 32 : 16); - - ClangASTType my_type(valobj_sp->GetClangType()); - if (my_type.GetNumTemplateArguments() >= 1) - { - TemplateArgumentKind kind; - ClangASTType pair_type = my_type.GetTemplateArgument(0, kind); - if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion) - return false; - m_pair_type = pair_type; - } - else - return false; - - return true; -} - -size_t -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren () -{ - return 2; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (m_pair_address != 0 && m_pair_type) - { - if (!m_pair_sp) - m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); - if (m_pair_sp) - return m_pair_sp->GetChildAtIndex(idx, true); - } - return lldb::ValueObjectSP(); -} - -bool -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (name == ConstString("first")) - return 0; - if (name == ConstString("second")) - return 1; - return UINT32_MAX; -} - -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)); -} - -/* - (lldb) fr var ibeg --ptr-depth 1 - (__gnu_cxx::__normal_iterator > >) ibeg = { - _M_current = 0x00000001001037a0 { - *_M_current = 1 - } - } - */ - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - static ConstString g_item_name; - if (!g_item_name) - g_item_name.SetCString("_M_current"); - if (!valobj_sp) - return NULL; - return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); -} diff --git a/source/DataFormatters/NSArray.cpp b/source/DataFormatters/NSArray.cpp deleted file mode 100644 index 640982efdb3c..000000000000 --- a/source/DataFormatters/NSArray.cpp +++ /dev/null @@ -1,706 +0,0 @@ -//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" -#include "lldb/Target/Target.h" - -#include "clang/AST/ASTContext.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update() = 0; - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSArrayMSyntheticFrontEnd () {} - - protected: - virtual lldb::addr_t - GetDataAddress () = 0; - - virtual uint64_t - GetUsedCount () = 0; - - virtual uint64_t - GetOffset () = 0; - - virtual uint64_t - GetSize () = 0; - - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - ClangASTType m_id_type; - std::vector m_children; - }; - - class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used; - uint32_t _priv1 : 2 ; - uint32_t _size : 30; - uint32_t _priv2 : 2; - uint32_t _offset : 30; - uint32_t _priv3; - uint32_t _data; - }; - struct DataDescriptor_64 - { - uint64_t _used; - uint64_t _priv1 : 2 ; - uint64_t _size : 62; - uint64_t _priv2 : 2; - uint64_t _offset : 62; - uint32_t _priv3; - uint64_t _data; - }; - public: - NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp); - - virtual bool - Update(); - - virtual - ~NSArrayMSyntheticFrontEnd_109 (); - - protected: - virtual lldb::addr_t - GetDataAddress (); - - virtual uint64_t - GetUsedCount (); - - virtual uint64_t - GetOffset (); - - virtual uint64_t - GetSize (); - - private: - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - }; - - class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used; - uint32_t _offset; - uint32_t _size : 28; - uint64_t _priv1 : 4; - uint32_t _priv2; - uint32_t _data; - }; - struct DataDescriptor_64 - { - uint64_t _used; - uint64_t _offset; - uint64_t _size : 60; - uint64_t _priv1 : 4; - uint32_t _priv2; - uint64_t _data; - }; - public: - NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp); - - virtual bool - Update(); - - virtual - ~NSArrayMSyntheticFrontEnd_1010 (); - - protected: - virtual lldb::addr_t - GetDataAddress (); - - virtual uint64_t - GetUsedCount (); - - virtual uint64_t - GetOffset (); - - virtual uint64_t - GetSize (); - - private: - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - }; - - class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSArrayISyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - uint64_t m_items; - lldb::addr_t m_data_ptr; - ClangASTType m_id_type; - std::vector m_children; - }; - - class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSArrayCodeRunningSyntheticFrontEnd (); - }; - } -} - -bool -lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint64_t value = 0; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"__NSArrayI")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - } - else if (!strcmp(class_name,"__NSArrayM")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - } - else if (!strcmp(class_name,"__NSCFArray")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - } - else - { - if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) - return false; - } - - stream.Printf("@\"%" PRIu64 " object%s\"", - value, - value == 1 ? "" : "s"); - return true; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp), - m_exe_ctx_ref(), - m_ptr_size(8), -m_id_type(), -m_children() -{ - if (valobj_sp) - { - clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext(); - if (ast) - m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy); - if (valobj_sp->GetProcessSP()) - m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); - } -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) : -NSArrayMSyntheticFrontEnd(valobj_sp), -m_data_32(NULL), -m_data_64(NULL) -{ -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) : -NSArrayMSyntheticFrontEnd(valobj_sp), -m_data_32(NULL), -m_data_64(NULL) -{ -} - -size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren () -{ - return GetUsedCount(); -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = GetDataAddress(); - size_t pyhs_idx = idx; - pyhs_idx += GetOffset(); - if (GetSize() <= pyhs_idx) - pyhs_idx -= GetSize(); - object_at_idx += (pyhs_idx * m_ptr_size); - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), - object_at_idx, - m_exe_ctx_ref, - m_id_type); - m_children.push_back(retval_sp); - return retval_sp; -} - -bool -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() -{ - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - return false; -} - -bool -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() -{ - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - return false; -} - -bool -lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress () -{ - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->_data : - m_data_64->_data; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_used : - m_data_64->_used; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_offset : - m_data_64->_offset; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : - m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress () -{ - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->_data : - m_data_64->_data; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_used : - m_data_64->_used; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_offset : - m_data_64->_offset; -} - -uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () -{ - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : - m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd (*valobj_sp.get()), - m_exe_ctx_ref (), - m_ptr_size (8), - m_items (0), - m_data_ptr (0) -{ - if (valobj_sp) - { - clang::ASTContext *ast = valobj_sp->GetClangType().GetASTContext(); - if (ast) - m_id_type = ClangASTType(ast, ast->ObjCBuiltinIdTy); - } -} - -lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd () -{ -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren () -{ - return m_items; -} - -bool -lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() -{ - m_ptr_size = 0; - m_items = 0; - m_data_ptr = 0; - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - m_items = process_sp->ReadPointerFromMemory(data_location, error); - if (error.Fail()) - return false; - m_data_ptr = data_location+m_ptr_size; - return false; -} - -bool -lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_ptr; - object_at_idx += (idx * m_ptr_size); - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Error error; - if (error.Fail()) - return lldb::ValueObjectSP(); - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), - object_at_idx, - m_exe_ctx_ref, - m_id_type); - m_children.push_back(retval_sp); - return retval_sp; -} - -SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return nullptr; - - lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); - if (!process_sp) - return NULL; - AppleObjCRuntime *runtime = (AppleObjCRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - if (!runtime) - return NULL; - - ClangASTType valobj_type(valobj_sp->GetClangType()); - Flags flags(valobj_type.GetTypeInfo()); - - if (flags.IsClear(eTypeIsPointer)) - { - Error error; - valobj_sp = valobj_sp->AddressOf(error); - if (error.Fail() || !valobj_sp) - return NULL; - } - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); - - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return NULL; - - if (!strcmp(class_name,"__NSArrayI")) - { - return (new NSArrayISyntheticFrontEnd(valobj_sp)); - } - else if (!strcmp(class_name,"__NSArrayM")) - { - if (runtime->GetFoundationVersion() >= 1100) - return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); - else - return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); - } - else - { - return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp)); - } -} - -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()) -{} - -size_t -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren () -{ - uint64_t count = 0; - if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) - return count; - return 0; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx); - if (valobj_sp) - valobj_sp->SetName(ConstString(idx_name.GetData())); - return valobj_sp; -} - -bool -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update() -{ - return false; -} - -bool -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - return 0; -} - -lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd () -{} diff --git a/source/DataFormatters/NSDictionary.cpp b/source/DataFormatters/NSDictionary.cpp deleted file mode 100644 index 30bc3acfbec7..000000000000 --- a/source/DataFormatters/NSDictionary.cpp +++ /dev/null @@ -1,702 +0,0 @@ -//===-- NSDictionary.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -#include "clang/AST/DeclCXX.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -static ClangASTType -GetLLDBNSPairType (TargetSP target_sp) -{ - ClangASTType clang_type; - - ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext(); - - if (target_ast_context) - { - ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair"); - - clang_type = target_ast_context->GetTypeForIdentifier(g___lldb_autogen_nspair); - - if (!clang_type) - { - clang_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); - - if (clang_type) - { - clang_type.StartTagDeclarationDefinition(); - ClangASTType id_clang_type = target_ast_context->GetBasicType (eBasicTypeObjCID); - clang_type.AddFieldToRecordType("key", id_clang_type, lldb::eAccessPublic, 0); - clang_type.AddFieldToRecordType("value", id_clang_type, lldb::eAccessPublic, 0); - clang_type.CompleteTagDeclarationDefinition(); - } - } - } - return clang_type; -} - -namespace lldb_private { - namespace formatters { - class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _szidx : 6; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _szidx : 6; - }; - - struct DictionaryItemDescriptor - { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; - }; - - public: - NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryISyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - lldb::addr_t m_data_ptr; - ClangASTType m_pair_type; - std::vector m_children; - }; - - class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _kvo : 1; - uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - uint32_t _keys_addr; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _kvo : 1; - uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - uint64_t _keys_addr; - }; - struct DictionaryItemDescriptor - { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; - }; - public: - NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryMSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - ClangASTType m_pair_type; - std::vector m_children; - }; - - class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSDictionaryCodeRunningSyntheticFrontEnd (); - }; - } -} - -template -bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - bool is_64bit = (ptr_size == 8); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint64_t value = 0; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"__NSDictionaryI")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } - else if (!strcmp(class_name,"__NSDictionaryM")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } - /*else if (!strcmp(class_name,"__NSCFDictionary")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); - if (error.Fail()) - return false; - if (is_64bit) - value &= ~0x0f1f000000000000UL; - }*/ - else - { - if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) - return false; - } - - stream.Printf("%s%" PRIu64 " %s%s", - (name_entries ? "@\"" : ""), - value, - (name_entries ? (value == 1 ? "entry" : "entries") : (value == 1 ? "key/value pair" : "key/value pairs")), - (name_entries ? "\"" : "")); - return true; -} - -SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - - lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); - if (!process_sp) - return NULL; - ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - if (!runtime) - return NULL; - - if (!valobj_sp->IsPointerType()) - { - Error error; - valobj_sp = valobj_sp->AddressOf(error); - if (error.Fail() || !valobj_sp) - return NULL; - } - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); - - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return NULL; - - if (!strcmp(class_name,"__NSDictionaryI")) - { - return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); - } - else if (!strcmp(class_name,"__NSDictionaryM")) - { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); - } - else - { - return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp)); - } -} - -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()) -{} - -size_t -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren () -{ - uint64_t count = 0; - if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) - return count; - return 0; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - StreamString key_fetcher_expr; - key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx); - StreamString value_fetcher_expr; - value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData()); - StreamString object_fetcher_expr; - object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData()); - lldb::ValueObjectSP child_sp; - EvaluateExpressionOptions options; - options.SetKeepInMemory(true); - m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), - GetViableFrame(m_backend.GetTargetSP().get()), - child_sp, - options); - if (child_sp) - child_sp->SetName(ConstString(idx_name.GetData())); - return child_sp; -} - -bool -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update() -{ - return false; -} - -bool -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - return 0; -} - -lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::~NSDictionaryCodeRunningSyntheticFrontEnd () -{} - -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_ptr_size(8), -m_order(lldb::eByteOrderInvalid), -m_data_32(NULL), -m_data_64(NULL), -m_pair_type() -{ -} - -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -size_t -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_data_32 && !m_data_64) - return 0; - return (m_data_32 ? m_data_32->_used : m_data_64->_used); -} - -bool -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() -{ - m_children.clear(); - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - m_ptr_size = 0; - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - m_order = process_sp->GetByteOrder(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - m_data_ptr = data_location + m_ptr_size; - return false; -} - -bool -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - uint32_t num_children = CalculateNumChildren(); - - if (idx >= num_children) - return lldb::ValueObjectSP(); - - if (m_children.empty()) - { - // do the scan phase - lldb::addr_t key_at_idx = 0, val_at_idx = 0; - - uint32_t tries = 0; - uint32_t test_idx = 0; - - while(tries < num_children) - { - key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size); - val_at_idx = key_at_idx + m_ptr_size; - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Error error; - key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - - test_idx++; - - if (!key_at_idx || !val_at_idx) - continue; - tries++; - - DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; - - m_children.push_back(descriptor); - } - } - - if (idx >= m_children.size()) // should never happen - return lldb::ValueObjectSP(); - - DictionaryItemDescriptor &dict_item = m_children[idx]; - if (!dict_item.valobj_sp) - { - if (!m_pair_type.IsValid()) - { - TargetSP target_sp(m_backend.GetTargetSP()); - if (!target_sp) - return ValueObjectSP(); - m_pair_type = GetLLDBNSPairType(target_sp); - } - if (!m_pair_type.IsValid()) - return ValueObjectSP(); - - DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); - - if (m_ptr_size == 8) - { - uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); - *data_ptr = dict_item.key_ptr; - *(data_ptr+1) = dict_item.val_ptr; - } - else - { - uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); - *data_ptr = dict_item.key_ptr; - *(data_ptr+1) = dict_item.val_ptr; - } - - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - DataExtractor data(buffer_sp, m_order, m_ptr_size); - dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_pair_type); - } - return dict_item.valobj_sp; -} - -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_ptr_size(8), -m_order(lldb::eByteOrderInvalid), -m_data_32(NULL), -m_data_64(NULL), -m_pair_type() -{ -} - -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -size_t -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_data_32 && !m_data_64) - return 0; - return (m_data_32 ? m_data_32->_used : m_data_64->_used); -} - -bool -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() -{ - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - m_order = process_sp->GetByteOrder(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - return false; -} - -bool -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); - lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); - - uint32_t num_children = CalculateNumChildren(); - - if (idx >= num_children) - return lldb::ValueObjectSP(); - - if (m_children.empty()) - { - // do the scan phase - lldb::addr_t key_at_idx = 0, val_at_idx = 0; - - uint32_t tries = 0; - uint32_t test_idx = 0; - - while(tries < num_children) - { - key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); - val_at_idx = m_values_ptr + (test_idx * m_ptr_size);; - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Error error; - key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - - test_idx++; - - if (!key_at_idx || !val_at_idx) - continue; - tries++; - - DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; - - m_children.push_back(descriptor); - } - } - - if (idx >= m_children.size()) // should never happen - return lldb::ValueObjectSP(); - - DictionaryItemDescriptor &dict_item = m_children[idx]; - if (!dict_item.valobj_sp) - { - if (!m_pair_type.IsValid()) - { - TargetSP target_sp(m_backend.GetTargetSP()); - if (!target_sp) - return ValueObjectSP(); - m_pair_type = GetLLDBNSPairType(target_sp); - } - if (!m_pair_type.IsValid()) - return ValueObjectSP(); - - DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); - - if (m_ptr_size == 8) - { - uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); - *data_ptr = dict_item.key_ptr; - *(data_ptr+1) = dict_item.val_ptr; - } - else - { - uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); - *data_ptr = dict_item.key_ptr; - *(data_ptr+1) = dict_item.val_ptr; - } - - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - DataExtractor data(buffer_sp, m_order, m_ptr_size); - dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_pair_type); - } - return dict_item.valobj_sp; -} - -template bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; - -template bool -lldb_private::formatters::NSDictionarySummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&) ; diff --git a/source/DataFormatters/NSIndexPath.cpp b/source/DataFormatters/NSIndexPath.cpp deleted file mode 100644 index 363bd5c0527e..000000000000 --- a/source/DataFormatters/NSIndexPath.cpp +++ /dev/null @@ -1,338 +0,0 @@ -//===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/DataFormatters/TypeSynthetic.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Symbol/ClangASTContext.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd -{ -public: - NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd (*valobj_sp.get()), - m_ptr_size(0), - m_ast_ctx(nullptr), - m_uint_star_type() - { - m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); - } - - virtual size_t - CalculateNumChildren () - { - return m_impl.GetNumIndexes(); - } - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx) - { - return m_impl.GetIndexAtIndex(idx, m_uint_star_type); - } - - virtual bool - Update() - { - m_impl.Clear(); - - m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext()); - if (!m_ast_ctx) - return false; - - m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false); - - static ConstString g__indexes("_indexes"); - static ConstString g__length("_length"); - - ProcessSP process_sp = m_backend.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint64_t info_bits(0),value_bits(0),payload(0); - - if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) - { - m_impl.m_inlined.SetIndexes(payload, *process_sp); - m_impl.m_mode = Mode::Inlined; - } - else - { - ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; - ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; - - bool has_indexes(false),has_length(false); - - for (size_t x = 0; - x < descriptor->GetNumIVars(); - x++) - { - const auto& ivar = descriptor->GetIVarAtIndex(x); - if (ivar.m_name == g__indexes) - { - _indexes_id = ivar; - has_indexes = true; - } - else if (ivar.m_name == g__length) - { - _length_id = ivar; - has_length = true; - } - - if (has_length && has_indexes) - break; - } - - if (has_length && has_indexes) - { - m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, - m_uint_star_type.GetPointerType(), - true).get(); - ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, - m_uint_star_type, - true)); - if (length_sp) - { - m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); - if (m_impl.m_outsourced.m_indexes) - m_impl.m_mode = Mode::Outsourced; - } - } - } - return false; - } - - virtual bool - MightHaveChildren () - { - if (m_impl.m_mode == Mode::Invalid) - return false; - return true; - } - - virtual size_t - GetIndexOfChildWithName (const ConstString &name) - { - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; - } - - virtual lldb::ValueObjectSP - GetSyntheticValue () { return nullptr; } - - virtual - ~NSIndexPathSyntheticFrontEnd () {} - -protected: - ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; - - enum class Mode { - Inlined, - Outsourced, - Invalid - }; - - struct Impl { - Mode m_mode; - - size_t - GetNumIndexes () - { - switch (m_mode) - { - case Mode::Inlined: - return m_inlined.GetNumIndexes(); - case Mode::Outsourced: - return m_outsourced.m_count; - default: - return 0; - } - } - - lldb::ValueObjectSP - GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) - { - if (idx >= GetNumIndexes()) - return nullptr; - switch (m_mode) - { - default: return nullptr; - case Mode::Inlined: - return m_inlined.GetIndexAtIndex (idx, desired_type); - case Mode::Outsourced: - return m_outsourced.GetIndexAtIndex (idx); - } - } - - struct InlinedIndexes { - public: - void SetIndexes(uint64_t value, Process& p) - { - m_indexes = value; - _lengthForInlinePayload(p.GetAddressByteSize()); - m_process = &p; - } - - size_t - GetNumIndexes () - { - return m_count; - } - - lldb::ValueObjectSP - GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) - { - std::pair value(_indexAtPositionForInlinePayload(idx)); - if (!value.second) - return nullptr; - - Value v; - if (m_ptr_size == 8) - { - Scalar scalar( (unsigned long long)value.first ); - v = Value(scalar); - } - else - { - Scalar scalar( (unsigned int)value.first ); - v = Value(scalar); - } - - v.SetClangType(desired_type); - - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - - return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); - } - - void - Clear () - { - m_indexes = 0; - m_count = 0; - m_ptr_size = 0; - m_process = nullptr; - } - - private: - uint64_t m_indexes; - size_t m_count; - uint32_t m_ptr_size; - Process *m_process; - - // cfr. Foundation for the details of this code - size_t _lengthForInlinePayload(uint32_t ptr_size) { - m_ptr_size = ptr_size; - if (m_ptr_size == 8) - m_count = ((m_indexes >> 3) & 0x7); - else - m_count = ((m_indexes >> 3) & 0x3); - return m_count; - } - - std::pair - _indexAtPositionForInlinePayload(size_t pos) - { - if (m_ptr_size == 8) - { - switch (pos) { - case 5: return {((m_indexes >> 51) & 0x1ff),true}; - case 4: return {((m_indexes >> 42) & 0x1ff),true}; - case 3: return {((m_indexes >> 33) & 0x1ff),true}; - case 2: return {((m_indexes >> 24) & 0x1ff),true}; - case 1: return {((m_indexes >> 15) & 0x1ff),true}; - case 0: return {((m_indexes >> 6) & 0x1ff),true}; - } - } - else - { - switch (pos) { - case 2: return {((m_indexes >> 23) & 0x1ff),true}; - case 1: return {((m_indexes >> 14) & 0x1ff),true}; - case 0: return {((m_indexes >> 5) & 0x1ff),true}; - } - } - return {0,false}; - } - - }; - struct OutsourcedIndexes { - ValueObject *m_indexes; - size_t m_count; - - lldb::ValueObjectSP - GetIndexAtIndex (size_t idx) - { - if (m_indexes) - { - ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true)); - return index_sp; - } - return nullptr; - } - - void - Clear () - { - m_indexes = nullptr; - m_count = 0; - } - }; - - union { - struct InlinedIndexes m_inlined; - struct OutsourcedIndexes m_outsourced; - }; - - void - Clear () - { - m_mode = Mode::Invalid; - m_inlined.Clear(); - m_outsourced.Clear(); - } - } m_impl; - - uint32_t m_ptr_size; - ClangASTContext* m_ast_ctx; - ClangASTType m_uint_star_type; -}; - -namespace lldb_private { - namespace formatters { - - SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) - { - if (valobj_sp) - return new NSIndexPathSyntheticFrontEnd(valobj_sp); - return nullptr; - } - } -} diff --git a/source/DataFormatters/NSSet.cpp b/source/DataFormatters/NSSet.cpp deleted file mode 100644 index 116904ce99b4..000000000000 --- a/source/DataFormatters/NSSet.cpp +++ /dev/null @@ -1,717 +0,0 @@ -//===-- NSSet.cpp ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/CXXFormatterFunctions.h" - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::formatters; - -namespace lldb_private { - namespace formatters { - class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _szidx : 6; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint32_t _szidx : 6; - }; - - struct SetItemDescriptor - { - lldb::addr_t item_ptr; - lldb::ValueObjectSP valobj_sp; - }; - - public: - NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetISyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - lldb::addr_t m_data_ptr; - std::vector m_children; - }; - - class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - - public: - NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSOrderedSetSyntheticFrontEnd (); - private: - uint32_t m_count; - std::map m_children; - }; - - class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - private: - struct DataDescriptor_32 - { - uint32_t _used : 26; - uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - }; - struct DataDescriptor_64 - { - uint64_t _used : 58; - uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - }; - struct SetItemDescriptor - { - lldb::addr_t item_ptr; - lldb::ValueObjectSP valobj_sp; - }; - public: - NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetMSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - std::vector m_children; - }; - - class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~NSSetCodeRunningSyntheticFrontEnd (); - }; - } -} - -template -bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) -{ - ProcessSP process_sp = valobj.GetProcessSP(); - if (!process_sp) - return false; - - ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - - if (!runtime) - return false; - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - - if (!descriptor.get() || !descriptor->IsValid()) - return false; - - uint32_t ptr_size = process_sp->GetAddressByteSize(); - bool is_64bit = (ptr_size == 8); - - lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); - - if (!valobj_addr) - return false; - - uint64_t value = 0; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return false; - - if (!strcmp(class_name,"__NSSetI")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } - else if (!strcmp(class_name,"__NSSetM")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } - /*else if (!strcmp(class_name,"__NSCFSet")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); - if (error.Fail()) - return false; - if (is_64bit) - value &= ~0x1fff000000000000UL; - } - else if (!strcmp(class_name,"NSCountedSet")) - { - Error error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); - if (error.Fail()) - return false; - value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error); - if (error.Fail()) - return false; - if (is_64bit) - value &= ~0x1fff000000000000UL; - }*/ - else - { - if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) - return false; - } - - stream.Printf("%s%" PRIu64 " %s%s", - (cf_style ? "@\"" : ""), - value, - (cf_style ? (value == 1 ? "value" : "values") : (value == 1 ? "object" : "objects")), - (cf_style ? "\"" : "")); - return true; -} - -SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); - if (!process_sp) - return NULL; - ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); - if (!runtime) - return NULL; - - if (!valobj_sp->IsPointerType()) - { - Error error; - valobj_sp = valobj_sp->AddressOf(error); - if (error.Fail() || !valobj_sp) - return NULL; - } - - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); - - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; - - const char* class_name = descriptor->GetClassName().GetCString(); - - if (!class_name || !*class_name) - return NULL; - - if (!strcmp(class_name,"__NSSetI")) - { - return (new NSSetISyntheticFrontEnd(valobj_sp)); - } - else if (!strcmp(class_name,"__NSSetM")) - { - return (new NSSetMSyntheticFrontEnd(valobj_sp)); - } - else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM"))) - { - return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code - } - else - { - return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL; - } -} - -lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_ptr_size(8), -m_data_32(NULL), -m_data_64(NULL) -{ - if (valobj_sp) - Update(); -} - -lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -size_t -lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_data_32 && !m_data_64) - return 0; - return (m_data_32 ? m_data_32->_used : m_data_64->_used); -} - -bool -lldb_private::formatters::NSSetISyntheticFrontEnd::Update() -{ - m_children.clear(); - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - m_ptr_size = 0; - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - if (valobj_sp->IsPointerType()) - { - valobj_sp = valobj_sp->Dereference(error); - if (error.Fail() || !valobj_sp) - return false; - } - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - m_data_ptr = data_location + m_ptr_size; - return false; -} - -bool -lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - uint32_t num_children = CalculateNumChildren(); - - if (idx >= num_children) - return lldb::ValueObjectSP(); - - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - - if (m_children.empty()) - { - // do the scan phase - lldb::addr_t obj_at_idx = 0; - - uint32_t tries = 0; - uint32_t test_idx = 0; - - while(tries < num_children) - { - obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); - if (!process_sp) - return lldb::ValueObjectSP(); - Error error; - obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - - test_idx++; - - if (!obj_at_idx) - continue; - tries++; - - SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; - - m_children.push_back(descriptor); - } - } - - if (idx >= m_children.size()) // should never happen - return lldb::ValueObjectSP(); - - SetItemDescriptor &set_item = m_children[idx]; - if (!set_item.valobj_sp) - { - auto ptr_size = process_sp->GetAddressByteSize(); - DataBufferHeap buffer(ptr_size,0); - switch (ptr_size) - { - case 0: // architecture has no clue?? - fail - return lldb::ValueObjectSP(); - case 4: - *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; - break; - case 8: - *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; - break; - default: - assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); - } - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - - DataExtractor data(buffer.GetBytes(), - buffer.GetByteSize(), - process_sp->GetByteOrder(), - process_sp->GetAddressByteSize()); - - set_item.valobj_sp = - CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); - } - return set_item.valobj_sp; -} - -lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_ptr_size(8), -m_data_32(NULL), -m_data_64(NULL) -{ - if (valobj_sp) - Update (); -} - -lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd () -{ - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; -} - -size_t -lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren () -{ - if (!m_data_32 && !m_data_64) - return 0; - return (m_data_32 ? m_data_32->_used : m_data_64->_used); -} - -bool -lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() -{ - m_children.clear(); - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = NULL; - delete m_data_64; - m_data_64 = NULL; - if (!valobj_sp) - return false; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Error error; - if (valobj_sp->IsPointerType()) - { - valobj_sp = valobj_sp->Dereference(error); - if (error.Fail() || !valobj_sp) - return false; - } - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; - if (m_ptr_size == 4) - { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); - } - else - { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); - } - if (error.Fail()) - return false; - return false; -} - -bool -lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); - - uint32_t num_children = CalculateNumChildren(); - - if (idx >= num_children) - return lldb::ValueObjectSP(); - - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - - if (m_children.empty()) - { - // do the scan phase - lldb::addr_t obj_at_idx = 0; - - uint32_t tries = 0; - uint32_t test_idx = 0; - - while(tries < num_children) - { - obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); - if (!process_sp) - return lldb::ValueObjectSP(); - Error error; - obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); - if (error.Fail()) - return lldb::ValueObjectSP(); - - test_idx++; - - if (!obj_at_idx) - continue; - tries++; - - SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; - - m_children.push_back(descriptor); - } - } - - if (idx >= m_children.size()) // should never happen - return lldb::ValueObjectSP(); - - SetItemDescriptor &set_item = m_children[idx]; - if (!set_item.valobj_sp) - { - auto ptr_size = process_sp->GetAddressByteSize(); - DataBufferHeap buffer(ptr_size,0); - switch (ptr_size) - { - case 0: // architecture has no clue?? - fail - return lldb::ValueObjectSP(); - case 4: - *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; - break; - case 8: - *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; - break; - default: - assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); - } - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - - DataExtractor data(buffer.GetBytes(), - buffer.GetByteSize(), - process_sp->GetByteOrder(), - process_sp->GetAddressByteSize()); - - set_item.valobj_sp = - CreateValueObjectFromData(idx_name.GetData(), - data, - m_exe_ctx_ref, - m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); - } - return set_item.valobj_sp; -} - -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_count(UINT32_MAX), -m_children() -{} - -size_t -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren () -{ - if (m_count != UINT32_MAX) - return m_count; - uint64_t count_temp; - if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp)) - return (m_count = count_temp); - return (m_count = 0); -} - -lldb::ValueObjectSP -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - auto iter = m_children.find(idx); - if (iter == m_children.end()) - { - lldb::ValueObjectSP retval_sp; - if (idx <= m_count) - { - retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx); - if (retval_sp) - { - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - retval_sp->SetName(ConstString(idx_name.GetData())); - } - m_children[idx] = retval_sp; - } - return retval_sp; - } - else - return iter->second; -} - -bool -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update() -{ - return false; -} - -bool -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::~NSOrderedSetSyntheticFrontEnd () -{ -} - -template bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - -template bool -lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); diff --git a/source/DataFormatters/StringPrinter.cpp b/source/DataFormatters/StringPrinter.cpp index a011cd553d0c..b114add50640 100644 --- a/source/DataFormatters/StringPrinter.cpp +++ b/source/DataFormatters/StringPrinter.cpp @@ -9,109 +9,26 @@ #include "lldb/DataFormatters/StringPrinter.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "llvm/Support/ConvertUTF.h" #include -#include #include using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; -// I can't use a std::unique_ptr for this because the Deleter is a template argument there -// and I want the same type to represent both pointers I want to free and pointers I don't need -// to free - which is what this class essentially is -// It's very specialized to the needs of this file, and not suggested for general use -template -struct StringPrinterBufferPointer -{ -public: - - typedef std::function Deleter; - - StringPrinterBufferPointer (std::nullptr_t ptr) : - m_data(nullptr), - m_size(0), - m_deleter() - {} - - StringPrinterBufferPointer(const T* bytes, S size, Deleter deleter = nullptr) : - m_data(bytes), - m_size(size), - m_deleter(deleter) - {} - - StringPrinterBufferPointer(const U* bytes, S size, Deleter deleter = nullptr) : - m_data((T*)bytes), - m_size(size), - m_deleter(deleter) - {} - - StringPrinterBufferPointer(StringPrinterBufferPointer&& rhs) : - m_data(rhs.m_data), - m_size(rhs.m_size), - m_deleter(rhs.m_deleter) - { - rhs.m_data = nullptr; - } - - StringPrinterBufferPointer(const StringPrinterBufferPointer& rhs) : - m_data(rhs.m_data), - m_size(rhs.m_size), - m_deleter(rhs.m_deleter) - { - rhs.m_data = nullptr; // this is why m_data has to be mutable - } - - const T* - GetBytes () const - { - return m_data; - } - - const S - GetSize () const - { - return m_size; - } - - ~StringPrinterBufferPointer () - { - if (m_data && m_deleter) - m_deleter(m_data); - m_data = nullptr; - } - - StringPrinterBufferPointer& - operator = (const StringPrinterBufferPointer& rhs) - { - if (m_data && m_deleter) - m_deleter(m_data); - m_data = rhs.m_data; - m_size = rhs.m_size; - m_deleter = rhs.m_deleter; - rhs.m_data = nullptr; - return *this; - } - -private: - mutable const T* m_data; - size_t m_size; - Deleter m_deleter; -}; - // we define this for all values of type but only implement it for those we care about // that's good because we get linker errors for any unsupported type -template -static StringPrinterBufferPointer<> +template +static StringPrinter::StringPrinterBufferPointer<> GetPrintableImpl(uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next); // mimic isprint() for Unicode codepoints @@ -142,10 +59,10 @@ isprint(char32_t codepoint) } template <> -StringPrinterBufferPointer<> -GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +StringPrinter::StringPrinterBufferPointer<> +GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) { - StringPrinterBufferPointer<> retval = {nullptr}; + StringPrinter::StringPrinterBufferPointer<> retval = {nullptr}; switch (*buffer) { @@ -212,10 +129,10 @@ ConvertUTF8ToCodePoint (unsigned char c0, unsigned char c1, unsigned char c2, un } template <> -StringPrinterBufferPointer<> -GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +StringPrinter::StringPrinterBufferPointer<> +GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) { - StringPrinterBufferPointer<> retval {nullptr}; + StringPrinter::StringPrinterBufferPointer<> retval {nullptr}; unsigned utf8_encoded_len = getNumBytesForUTF8(*buffer); @@ -232,7 +149,7 @@ GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, { case 1: // this is just an ASCII byte - ask ASCII - return GetPrintableImpl(buffer, buffer_end, next); + return GetPrintableImpl(buffer, buffer_end, next); case 2: codepoint = ConvertUTF8ToCodePoint((unsigned char)*buffer, (unsigned char)*(buffer+1)); break; @@ -309,23 +226,40 @@ GetPrintableImpl (uint8_t* buffer, uint8_t* buffer_end, // Given a sequence of bytes, this function returns: // a sequence of bytes to actually print out + a length // the following unscanned position of the buffer is in next -static StringPrinterBufferPointer<> -GetPrintable(StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) +static StringPrinter::StringPrinterBufferPointer<> +GetPrintable(StringPrinter::StringElementType type, uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) { if (!buffer) return {nullptr}; switch (type) { - case StringElementType::ASCII: - return GetPrintableImpl(buffer, buffer_end, next); - case StringElementType::UTF8: - return GetPrintableImpl(buffer, buffer_end, next); + case StringPrinter::StringElementType::ASCII: + return GetPrintableImpl(buffer, buffer_end, next); + case StringPrinter::StringElementType::UTF8: + return GetPrintableImpl(buffer, buffer_end, next); default: return {nullptr}; } } +StringPrinter::EscapingHelper +StringPrinter::GetDefaultEscapingHelper (GetPrintableElementType elem_type) +{ + switch (elem_type) + { + case GetPrintableElementType::UTF8: + return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> { + return GetPrintable(StringPrinter::StringElementType::UTF8, buffer, buffer_end, next); + }; + case GetPrintableElementType::ASCII: + return [] (uint8_t* buffer, uint8_t* buffer_end, uint8_t*& next) -> StringPrinter::StringPrinterBufferPointer<> { + return GetPrintable(StringPrinter::StringElementType::ASCII, buffer, buffer_end, next); + }; + } + llvm_unreachable("bad element type"); +} + // use this call if you already have an LLDB-side buffer for the data template static bool @@ -334,41 +268,44 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType UTF8**, UTF8*, ConversionFlags), - const DataExtractor& data, - Stream& stream, - char prefix_token, - char quote, - uint32_t sourceSize, - bool escapeNonPrintables) + const StringPrinter::ReadBufferAndDumpToStreamOptions& dump_options) { - if (prefix_token != 0) - stream.Printf("%c",prefix_token); - if (quote != 0) - stream.Printf("%c",quote); + Stream &stream(*dump_options.GetStream()); + if (dump_options.GetPrefixToken() != 0) + stream.Printf("%s",dump_options.GetPrefixToken()); + if (dump_options.GetQuote() != 0) + stream.Printf("%c",dump_options.GetQuote()); + auto data(dump_options.GetData()); + auto source_size(dump_options.GetSourceSize()); if (data.GetByteSize() && data.GetDataStart() && data.GetDataEnd()) { const int bufferSPSize = data.GetByteSize(); - if (sourceSize == 0) + if (dump_options.GetSourceSize() == 0) { const int origin_encoding = 8*sizeof(SourceDataType); - sourceSize = bufferSPSize/(origin_encoding / 4); + source_size = bufferSPSize/(origin_encoding / 4); } const SourceDataType *data_ptr = (const SourceDataType*)data.GetDataStart(); - const SourceDataType *data_end_ptr = data_ptr + sourceSize; + const SourceDataType *data_end_ptr = data_ptr + source_size; - while (data_ptr < data_end_ptr) + const bool zero_is_terminator = dump_options.GetBinaryZeroIsTerminator(); + + if (zero_is_terminator) { - if (!*data_ptr) + while (data_ptr < data_end_ptr) { - data_end_ptr = data_ptr; - break; + if (!*data_ptr) + { + data_end_ptr = data_ptr; + break; + } + data_ptr++; } - data_ptr++; + + data_ptr = (const SourceDataType*)data.GetDataStart(); } - data_ptr = (const SourceDataType*)data.GetDataStart(); - lldb::DataBufferSP utf8_data_buffer_sp; UTF8* utf8_data_ptr = nullptr; UTF8* utf8_data_end_ptr = nullptr; @@ -379,14 +316,26 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); 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, lenientConversion ); + if (false == zero_is_terminator) + utf8_data_end_ptr = utf8_data_ptr; utf8_data_ptr = (UTF8*)utf8_data_buffer_sp->GetBytes(); // needed because the ConvertFunction will change the value of the data_ptr } else { // just copy the pointers - the cast is necessary to make the compiler happy // but this should only happen if we are reading UTF8 data - utf8_data_ptr = (UTF8*)data_ptr; - utf8_data_end_ptr = (UTF8*)data_end_ptr; + utf8_data_ptr = const_cast(reinterpret_cast(data_ptr)); + utf8_data_end_ptr = const_cast(reinterpret_cast(data_end_ptr)); + } + + const bool escape_non_printables = dump_options.GetEscapeNonPrintables(); + lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; + if (escape_non_printables) + { + if (Language *language = Language::FindPlugin(dump_options.GetLanguage())) + escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8); + else + escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::UTF8); } // since we tend to accept partial data (and even partially malformed data) @@ -394,13 +343,13 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType // hence we need to take a slower route and ensure we stay within boundaries for (;utf8_data_ptr < utf8_data_end_ptr;) { - if (!*utf8_data_ptr) + if (zero_is_terminator && !*utf8_data_ptr) break; - if (escapeNonPrintables) + if (escape_non_printables) { uint8_t* next_data = nullptr; - auto printable = GetPrintable(StringElementType::UTF8, utf8_data_ptr, utf8_data_end_ptr, next_data); + auto printable = escaping_callback(utf8_data_ptr, utf8_data_end_ptr, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) @@ -421,23 +370,39 @@ DumpUTFBufferToStream (ConversionResult (*ConvertFunction) (const SourceDataType } } } - if (quote != 0) - stream.Printf("%c",quote); + if (dump_options.GetQuote() != 0) + stream.Printf("%c",dump_options.GetQuote()); + if (dump_options.GetSuffixToken() != 0) + stream.Printf("%s",dump_options.GetSuffixToken()); + if (dump_options.GetIsTruncated()) + stream.Printf("..."); return true; } -lldb_private::formatters::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) : +lldb_private::formatters::StringPrinter::ReadStringAndDumpToStreamOptions::ReadStringAndDumpToStreamOptions (ValueObject& valobj) : ReadStringAndDumpToStreamOptions() { SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); } -lldb_private::formatters::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) : +lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (ValueObject& valobj) : ReadBufferAndDumpToStreamOptions() { SetEscapeNonPrintables(valobj.GetTargetSP()->GetDebugger().GetEscapeNonPrintables()); } +lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions::ReadBufferAndDumpToStreamOptions (const ReadStringAndDumpToStreamOptions& options) : + ReadBufferAndDumpToStreamOptions() +{ + SetStream(options.GetStream()); + SetPrefixToken(options.GetPrefixToken()); + SetSuffixToken(options.GetSuffixToken()); + SetQuote(options.GetQuote()); + SetEscapeNonPrintables(options.GetEscapeNonPrintables()); + SetBinaryZeroIsTerminator(options.GetBinaryZeroIsTerminator()); + SetLanguage(options.GetLanguage()); +} + namespace lldb_private { @@ -447,7 +412,7 @@ namespace formatters template <> bool -ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +StringPrinter::ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); Error my_error; @@ -458,11 +423,20 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOp return false; size_t size; + const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); + bool is_truncated = false; if (options.GetSourceSize() == 0) - size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); + size = max_size; else if (!options.GetIgnoreMaxLength()) - size = std::min(options.GetSourceSize(),process_sp->GetTarget().GetMaximumSizeOfStringSummary()); + { + size = options.GetSourceSize(); + if (size > max_size) + { + size = max_size; + is_truncated = true; + } + } else size = options.GetSourceSize(); @@ -473,25 +447,35 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOp if (my_error.Fail()) return false; - char prefix_token = options.GetPrefixToken(); + const char* prefix_token = options.GetPrefixToken(); char quote = options.GetQuote(); if (prefix_token != 0) - options.GetStream()->Printf("%c%c",prefix_token,quote); + options.GetStream()->Printf("%s%c",prefix_token,quote); else if (quote != 0) options.GetStream()->Printf("%c",quote); uint8_t* data_end = buffer_sp->GetBytes()+buffer_sp->GetByteSize(); + const bool escape_non_printables = options.GetEscapeNonPrintables(); + lldb_private::formatters::StringPrinter::EscapingHelper escaping_callback; + if (escape_non_printables) + { + if (Language *language = Language::FindPlugin(options.GetLanguage())) + escaping_callback = language->GetStringPrinterEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); + else + escaping_callback = lldb_private::formatters::StringPrinter::GetDefaultEscapingHelper(lldb_private::formatters::StringPrinter::GetPrintableElementType::ASCII); + } + // since we tend to accept partial data (and even partially malformed data) // we might end up with no NULL terminator before the end_ptr // hence we need to take a slower route and ensure we stay within boundaries for (uint8_t* data = buffer_sp->GetBytes(); *data && (data < data_end);) { - if (options.GetEscapeNonPrintables()) + if (escape_non_printables) { uint8_t* next_data = nullptr; - auto printable = GetPrintable(StringElementType::ASCII, data, data_end, next_data); + auto printable = escaping_callback(data, data_end, next_data); auto printable_bytes = printable.GetBytes(); auto printable_size = printable.GetSize(); if (!printable_bytes || !next_data) @@ -511,16 +495,23 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOp data++; } } - - if (quote != 0) + + const char* suffix_token = options.GetSuffixToken(); + + if (suffix_token != 0) + options.GetStream()->Printf("%c%s",quote, suffix_token); + else if (quote != 0) options.GetStream()->Printf("%c",quote); + if (is_truncated) + options.GetStream()->Printf("..."); + return true; } template static bool -ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options, +ReadUTFBufferAndDumpToStream (const StringPrinter::ReadStringAndDumpToStreamOptions& options, ConversionResult (*ConvertFunction) (const SourceDataType**, const SourceDataType*, UTF8**, @@ -550,14 +541,23 @@ ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options, uint32_t sourceSize = options.GetSourceSize(); bool needs_zero_terminator = options.GetNeedsZeroTermination(); + + bool is_truncated = false; + const auto max_size = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); if (!sourceSize) { - sourceSize = process_sp->GetTarget().GetMaximumSizeOfStringSummary(); + sourceSize = max_size; needs_zero_terminator = true; } else if (!options.GetIgnoreMaxLength()) - sourceSize = std::min(sourceSize,process_sp->GetTarget().GetMaximumSizeOfStringSummary()); + { + if (sourceSize > max_size) + { + sourceSize = max_size; + is_truncated = true; + } + } const int bufferSPSize = sourceSize * type_width; @@ -581,13 +581,18 @@ ReadUTFBufferAndDumpToStream (const ReadStringAndDumpToStreamOptions& options, } DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + + StringPrinter::ReadBufferAndDumpToStreamOptions dump_options(options); + dump_options.SetData(data); + dump_options.SetSourceSize(sourceSize); + dump_options.SetIsTruncated(is_truncated); - return DumpUTFBufferToStream(ConvertFunction, data, *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), sourceSize, options.GetEscapeNonPrintables()); + return DumpUTFBufferToStream(ConvertFunction, dump_options); } template <> bool -ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +StringPrinter::ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options) { return ReadUTFBufferAndDumpToStream(options, nullptr); @@ -595,7 +600,7 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOpt template <> bool -ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +StringPrinter::ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options) { return ReadUTFBufferAndDumpToStream(options, ConvertUTF16toUTF8); @@ -603,7 +608,7 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOp template <> bool -ReadStringAndDumpToStream (ReadStringAndDumpToStreamOptions options) +StringPrinter::ReadStringAndDumpToStream (const ReadStringAndDumpToStreamOptions& options) { return ReadUTFBufferAndDumpToStream(options, ConvertUTF32toUTF8); @@ -611,16 +616,16 @@ ReadStringAndDumpToStream (ReadStringAndDumpToStreamOp template <> bool -ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +StringPrinter::ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); - return DumpUTFBufferToStream(nullptr, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); + return DumpUTFBufferToStream(nullptr, options); } template <> bool -ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +StringPrinter::ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options) { // treat ASCII the same as UTF8 // FIXME: can we optimize ASCII some more? @@ -629,20 +634,20 @@ ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOp template <> bool -ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +StringPrinter::ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); - return DumpUTFBufferToStream(ConvertUTF16toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); + return DumpUTFBufferToStream(ConvertUTF16toUTF8, options); } template <> bool -ReadBufferAndDumpToStream (ReadBufferAndDumpToStreamOptions options) +StringPrinter::ReadBufferAndDumpToStream (const ReadBufferAndDumpToStreamOptions& options) { assert(options.GetStream() && "need a Stream to print the string to"); - return DumpUTFBufferToStream(ConvertUTF32toUTF8, options.GetData(), *options.GetStream(), options.GetPrefixToken(), options.GetQuote(), options.GetSourceSize(), options.GetEscapeNonPrintables()); + return DumpUTFBufferToStream(ConvertUTF32toUTF8, options); } } // namespace formatters diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp index b05cea55ff51..636d935b7625 100644 --- a/source/DataFormatters/TypeCategory.cpp +++ b/source/DataFormatters/TypeCategory.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "lldb/DataFormatters/TypeCategory.h" +#include "lldb/Target/Language.h" // C Includes // C++ Includes @@ -18,7 +19,8 @@ using namespace lldb; using namespace lldb_private; TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener* clist, - ConstString name) : + ConstString name, + std::initializer_list langs) : m_format_cont("format","regex-format",clist), m_summary_cont("summary","regex-summary",clist), m_filter_cont("filter","regex-filter",clist), @@ -29,8 +31,118 @@ m_validator_cont("validator","regex-validator",clist), m_enabled(false), m_change_listener(clist), m_mutex(Mutex::eMutexTypeRecursive), -m_name(name) -{} +m_name(name), +m_languages() +{ + for (const lldb::LanguageType lang : langs) + AddLanguage(lang); +} + +static bool +IsApplicable(lldb::LanguageType category_lang, + lldb::LanguageType valobj_lang) +{ + switch (category_lang) + { + // these are not languages that LLDB would ordinarily deal with + // only allow an exact equality here, since we really don't know + // any better + case eLanguageTypeAda83: + case eLanguageTypeCobol74: + case eLanguageTypeCobol85: + case eLanguageTypeFortran77: + case eLanguageTypeFortran90: + case eLanguageTypePascal83: + case eLanguageTypeModula2: + case eLanguageTypeJava: + case eLanguageTypeAda95: + case eLanguageTypeFortran95: + case eLanguageTypePLI: + case eLanguageTypeUPC: + case eLanguageTypeD: + case eLanguageTypePython: + return category_lang == valobj_lang; + + // the C family, we consider it as one + case eLanguageTypeC89: + case eLanguageTypeC: + case eLanguageTypeC99: + return valobj_lang == eLanguageTypeC89 || + valobj_lang == eLanguageTypeC || + valobj_lang == eLanguageTypeC99; + + // ObjC knows about C and itself + case eLanguageTypeObjC: + return valobj_lang == eLanguageTypeC89 || + valobj_lang == eLanguageTypeC || + valobj_lang == eLanguageTypeC99 || + valobj_lang == eLanguageTypeObjC; + + // C++ knows about C and C++ + case eLanguageTypeC_plus_plus: + return valobj_lang == eLanguageTypeC89 || + valobj_lang == eLanguageTypeC || + valobj_lang == eLanguageTypeC99 || + valobj_lang == eLanguageTypeC_plus_plus; + + // ObjC++ knows about C,C++,ObjC and ObjC++ + case eLanguageTypeObjC_plus_plus: + return valobj_lang == eLanguageTypeC89 || + valobj_lang == eLanguageTypeC || + valobj_lang == eLanguageTypeC99 || + valobj_lang == eLanguageTypeC_plus_plus || + valobj_lang == eLanguageTypeObjC; + + default: + case eLanguageTypeUnknown: + return true; + } +} + +bool +TypeCategoryImpl::IsApplicable (ValueObject& valobj) +{ + lldb::LanguageType valobj_lang = valobj.GetObjectRuntimeLanguage(); + for (size_t idx = 0; + idx < GetNumLanguages(); + idx++) + { + const lldb::LanguageType category_lang = GetLanguageAtIndex(idx); + if (::IsApplicable(category_lang,valobj_lang)) + return true; + } + return false; +} + +size_t +TypeCategoryImpl::GetNumLanguages () +{ + if (m_languages.empty()) + return 1; + return m_languages.size(); +} + +lldb::LanguageType +TypeCategoryImpl::GetLanguageAtIndex (size_t idx) +{ + if (m_languages.empty()) + return lldb::eLanguageTypeUnknown; + return m_languages[idx]; +} + +void +TypeCategoryImpl::AddLanguage (lldb::LanguageType lang) +{ + m_languages.push_back(lang); +} + +bool +TypeCategoryImpl::HasLanguage (lldb::LanguageType lang) +{ + const auto iter = std::find(m_languages.begin(), m_languages.end(), lang), + end = m_languages.end(); + return (iter != end); +} bool TypeCategoryImpl::Get (ValueObject& valobj, @@ -38,7 +150,7 @@ TypeCategoryImpl::Get (ValueObject& valobj, lldb::TypeFormatImplSP& entry, uint32_t* reason) { - if (!IsEnabled()) + if (!IsEnabled() || !IsApplicable(valobj)) return false; if (GetTypeFormatsContainer()->Get(candidates, entry, reason)) return true; @@ -54,7 +166,7 @@ TypeCategoryImpl::Get (ValueObject& valobj, lldb::TypeSummaryImplSP& entry, uint32_t* reason) { - if (!IsEnabled()) + if (!IsEnabled() || !IsApplicable(valobj)) return false; if (GetTypeSummariesContainer()->Get(candidates, entry, reason)) return true; @@ -70,7 +182,7 @@ TypeCategoryImpl::Get (ValueObject& valobj, lldb::SyntheticChildrenSP& entry, uint32_t* reason) { - if (!IsEnabled()) + if (!IsEnabled() || !IsApplicable(valobj)) return false; TypeFilterImpl::SharedPointer filter_sp; uint32_t reason_filter = 0; @@ -567,3 +679,30 @@ TypeCategoryImpl::Enable (bool value, uint32_t position) if (m_change_listener) m_change_listener->Changed(); } + +std::string +TypeCategoryImpl::GetDescription () +{ + StreamString stream; + stream.Printf("%s (%s", + GetName(), + (IsEnabled() ? "enabled" : "disabled")); + StreamString lang_stream; + lang_stream.Printf(", applicable for language(s): "); + bool print_lang = false; + for (size_t idx = 0; + idx < GetNumLanguages(); + idx++) + { + const lldb::LanguageType lang = GetLanguageAtIndex(idx); + if (lang != lldb::eLanguageTypeUnknown) + print_lang = true; + lang_stream.Printf("%s%s", + Language::GetNameForLanguageType(lang), + idx+1Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32, + match.GetTypeName().GetCString(), + match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", + match.DidStripReference() ? "strip-reference" : "no-strip-reference", + match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef", + match.GetReason()); + } + } + for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeFormatImplSP current_format; if (log) - log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName()); - if (!category_sp->Get(valobj, matches, current_format, &reason_why)) + log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName()); + if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } @@ -246,25 +256,35 @@ TypeCategoryMap::GetFormat (ValueObject& valobj, } lldb::TypeSummaryImplSP -TypeCategoryMap::GetSummaryFormat (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +TypeCategoryMap::GetSummaryFormat (FormattersMatchData& match_data) { Mutex::Locker locker(m_map_mutex); uint32_t reason_why; ActiveCategoriesIterator begin, end = m_active_categories.end(); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (log) + { + for (auto match : match_data.GetMatchesVector()) + { + log->Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32, + match.GetTypeName().GetCString(), + match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", + match.DidStripReference() ? "strip-reference" : "no-strip-reference", + match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef", + match.GetReason()); + } + } + for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeSummaryImplSP current_format; if (log) - log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName()); - if (!category_sp->Get(valobj, matches, current_format, &reason_why)) + log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName()); + if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } @@ -275,8 +295,7 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj, #ifndef LLDB_DISABLE_PYTHON lldb::SyntheticChildrenSP -TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +TypeCategoryMap::GetSyntheticChildren (FormattersMatchData& match_data) { Mutex::Locker locker(m_map_mutex); @@ -284,17 +303,28 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, ActiveCategoriesIterator begin, end = m_active_categories.end(); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (log) + { + for (auto match : match_data.GetMatchesVector()) + { + log->Printf("[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s reason = %" PRIu32, + match.GetTypeName().GetCString(), + match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", + match.DidStripReference() ? "strip-reference" : "no-strip-reference", + match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef", + match.GetReason()); + } + } + for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::SyntheticChildrenSP current_format; if (log) - log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName()); - if (!category_sp->Get(valobj, matches, current_format, &reason_why)) + log->Printf("[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName()); + if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } @@ -305,25 +335,35 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj, #endif lldb::TypeValidatorImplSP -TypeCategoryMap::GetValidator (ValueObject& valobj, - lldb::DynamicValueType use_dynamic) +TypeCategoryMap::GetValidator (FormattersMatchData& match_data) { Mutex::Locker locker(m_map_mutex); uint32_t reason_why; ActiveCategoriesIterator begin, end = m_active_categories.end(); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); + if (log) + { + for (auto match : match_data.GetMatchesVector()) + { + log->Printf("[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = %" PRIu32, + match.GetTypeName().GetCString(), + match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", + match.DidStripReference() ? "strip-reference" : "no-strip-reference", + match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef", + match.GetReason()); + } + } + for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category_sp = *begin; lldb::TypeValidatorImplSP current_format; if (log) - log->Printf("\n[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName()); - if (!category_sp->Get(valobj, matches, current_format, &reason_why)) + log->Printf("[CategoryMap::GetValidator] Trying to use category %s", category_sp->GetName()); + if (!category_sp->Get(match_data.GetValueObject(), match_data.GetMatchesVector(), current_format, &reason_why)) continue; return current_format; } @@ -333,7 +373,7 @@ TypeCategoryMap::GetValidator (ValueObject& valobj, } void -TypeCategoryMap::LoopThrough(CallbackType callback, void* param) +TypeCategoryMap::ForEach(ForEachCallback callback) { if (callback) { @@ -345,8 +385,7 @@ TypeCategoryMap::LoopThrough(CallbackType callback, void* param) for (begin = m_active_categories.begin(); begin != end; begin++) { lldb::TypeCategoryImplSP category = *begin; - ConstString type = ConstString(category->GetName()); - if (!callback(param, category)) + if (!callback(category)) break; } } @@ -359,7 +398,7 @@ TypeCategoryMap::LoopThrough(CallbackType callback, void* param) if (pos->second->IsEnabled()) continue; KeyType type = pos->first; - if (!callback(param, pos->second)) + if (!callback(pos->second)) break; } } diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp index c4a65fea7da5..6ab8d298f94b 100644 --- a/source/DataFormatters/TypeFormat.cpp +++ b/source/DataFormatters/TypeFormat.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/DataFormatters/TypeFormat.h" + // C Includes // C++ Includes @@ -17,15 +19,11 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" -#include "lldb/Core/Debugger.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/Timer.h" #include "lldb/DataFormatters/FormatManager.h" -#include "lldb/DataFormatters/TypeFormat.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/TypeList.h" -#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -91,13 +89,13 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj, } else { - ClangASTType clang_type = value.GetClangType (); - if (clang_type) + CompilerType compiler_type = value.GetCompilerType (); + if (compiler_type) { // put custom bytes to display in the DataExtractor to override the default value logic if (GetFormat() == eFormatCString) { - lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags + lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data as a string @@ -122,7 +120,7 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj, } StreamString sstr; - clang_type.DumpTypeValue (&sstr, // The stream to use for display + 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" @@ -134,7 +132,7 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj, // for a formatting error (or else we wouldn't be able to reformat // until a next update), an empty string is treated as a "false" // return from here, but that's about as severe as we get - // ClangASTType::DumpTypeValue() should always return + // CompilerType::DumpTypeValue() should always return // something, even if that something is an error message if (sstr.GetString().empty()) dest.clear(); @@ -192,7 +190,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, return false; auto iter = m_types.find(valobj_key), end = m_types.end(); - ClangASTType valobj_enum_type; + CompilerType valobj_enum_type; if (iter == end) { // probably a redundant check @@ -208,9 +206,9 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, { if (!type_sp) continue; - if ( (type_sp->GetClangForwardType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration) + if ( (type_sp->GetForwardCompilerType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration) { - valobj_enum_type = type_sp->GetClangFullType(); + valobj_enum_type = type_sp->GetFullCompilerType (); m_types.emplace(valobj_key,valobj_enum_type); break; } diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp index fa06f297f829..2806ba20c6a9 100644 --- a/source/DataFormatters/TypeSummary.cpp +++ b/source/DataFormatters/TypeSummary.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "lldb/DataFormatters/TypeSummary.h" + // C Includes // C++ Includes @@ -19,16 +21,13 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/Timer.h" -#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" -#include "lldb/Host/Host.h" - using namespace lldb; using namespace lldb_private; @@ -76,15 +75,17 @@ TypeSummaryOptions::SetCapping (lldb::TypeSummaryCapping cap) return *this; } -TypeSummaryImpl::TypeSummaryImpl (const TypeSummaryImpl::Flags& flags) : -m_flags(flags) +TypeSummaryImpl::TypeSummaryImpl (Kind kind, + const TypeSummaryImpl::Flags& flags) : + m_flags(flags), + m_kind(kind) { } StringSummaryFormat::StringSummaryFormat (const TypeSummaryImpl::Flags& flags, const char *format_cstr) : - TypeSummaryImpl(flags), + TypeSummaryImpl(Kind::eSummaryString,flags), m_format_str() { SetSummaryString (format_cstr); @@ -170,7 +171,7 @@ StringSummaryFormat::GetDescription () CXXFunctionSummaryFormat::CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags, Callback impl, const char* description) : -TypeSummaryImpl(flags), + TypeSummaryImpl(Kind::eCallback,flags), m_impl(impl), m_description(description ? description : "") { @@ -193,28 +194,25 @@ std::string CXXFunctionSummaryFormat::GetDescription () { StreamString sstr; - sstr.Printf ("`%s (%p) `%s%s%s%s%s%s%s", m_description.c_str(), - static_cast(&m_impl), + sstr.Printf ("%s%s%s%s%s%s%s %s", Cascades() ? "" : " (not cascading)", !DoesPrintChildren(nullptr) ? "" : " (show children)", !DoesPrintValue(nullptr) ? " (hide value)" : "", IsOneLiner() ? " (one-line printout)" : "", SkipsPointers() ? " (skip pointers)" : "", SkipsReferences() ? " (skip references)" : "", - HideNames(nullptr) ? " (hide member names)" : ""); + HideNames(nullptr) ? " (hide member names)" : "", + m_description.c_str()); return sstr.GetString(); } -#ifndef LLDB_DISABLE_PYTHON - - ScriptSummaryFormat::ScriptSummaryFormat (const TypeSummaryImpl::Flags& flags, const char * function_name, const char * python_script) : -TypeSummaryImpl(flags), -m_function_name(), -m_python_script(), -m_script_function_sp() + TypeSummaryImpl(Kind::eScript,flags), + m_function_name(), + m_python_script(), + m_script_function_sp() { if (function_name) m_function_name.assign(function_name); @@ -227,15 +225,9 @@ ScriptSummaryFormat::FormatObject (ValueObject *valobj, std::string& retval, const TypeSummaryOptions& options) { - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - if (!valobj) return false; - Host::SetCrashDescriptionWithFormat("[Python summary] Name: %s - Function: %s", - valobj->GetName().AsCString("unknown"), - m_function_name.c_str()); - TargetSP target_sp(valobj->GetTargetSP()); if (!target_sp) @@ -275,5 +267,3 @@ ScriptSummaryFormat::GetDescription () return sstr.GetString(); } - -#endif // #ifndef LLDB_DISABLE_PYTHON diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp index 5bd8d30e4873..e49cd99b02ea 100644 --- a/source/DataFormatters/TypeSynthetic.cpp +++ b/source/DataFormatters/TypeSynthetic.cpp @@ -22,8 +22,7 @@ #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Target/StackFrame.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -111,11 +110,10 @@ std::string CXXSyntheticChildren::GetDescription() { StreamString sstr; - sstr.Printf("%s%s%s Generator at %p - %s", + sstr.Printf("%s%s%s %s", Cascades() ? "" : " (not cascading)", SkipsPointers() ? " (skip pointers)" : "", SkipsReferences() ? " (skip references)" : "", - reinterpret_cast(reinterpret_cast(m_create_callback)), m_description.c_str()); return sstr.GetString(); @@ -136,7 +134,7 @@ lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromAddress (const char* name, uint64_t address, const ExecutionContext& exe_ctx, - ClangASTType type) + CompilerType type) { ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromAddress(name, address, exe_ctx, type)); if (valobj_sp) @@ -148,7 +146,7 @@ lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData (const char* name, const DataExtractor& data, const ExecutionContext& exe_ctx, - ClangASTType type) + CompilerType type) { ValueObjectSP valobj_sp(ValueObject::CreateValueObjectFromData(name, data, exe_ctx, type)); if (valobj_sp) @@ -202,7 +200,15 @@ ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren () { if (!m_wrapper_sp || m_interpreter == NULL) return 0; - return m_interpreter->CalculateNumChildren(m_wrapper_sp); + return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); +} + +size_t +ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren (uint32_t max) +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return 0; + return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); } bool diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp index 7c794ee2ddac..04c291283546 100644 --- a/source/DataFormatters/ValueObjectPrinter.cpp +++ b/source/DataFormatters/ValueObjectPrinter.cpp @@ -13,33 +13,28 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Debugger.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; -DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) : -DumpValueObjectOptions() -{ - m_use_dynamic = valobj.GetDynamicValueType(); - m_use_synthetic = valobj.IsSynthetic(); -} - ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, Stream* s) { if (valobj) { DumpValueObjectOptions options(*valobj); - Init (valobj,s,options,options.m_max_ptr_depth,0); + Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); } else { DumpValueObjectOptions options; - Init (valobj,s,options,options.m_max_ptr_depth,0); + Init (valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); } } @@ -47,42 +42,48 @@ ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, Stream* s, const DumpValueObjectOptions& options) { - Init(valobj,s,options,options.m_max_ptr_depth,0); + Init(valobj,s,options,m_options.m_max_ptr_depth,0, nullptr); } ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj, Stream* s, const DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth) + const DumpValueObjectOptions::PointerDepth& ptr_depth, + uint32_t curr_depth, + InstancePointersSetSP printed_instance_pointers) { - Init(valobj,s,options,ptr_depth,curr_depth); + Init(valobj,s,options,ptr_depth,curr_depth, printed_instance_pointers); } void ValueObjectPrinter::Init (ValueObject* valobj, Stream* s, const DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth) + const DumpValueObjectOptions::PointerDepth& ptr_depth, + uint32_t curr_depth, + InstancePointersSetSP printed_instance_pointers) { m_orig_valobj = valobj; m_valobj = nullptr; m_stream = s; - this->options = options; + m_options = options; m_ptr_depth = ptr_depth; m_curr_depth = curr_depth; assert (m_orig_valobj && "cannot print a NULL ValueObject"); assert (m_stream && "cannot print to a NULL Stream"); m_should_print = eLazyBoolCalculate; m_is_nil = eLazyBoolCalculate; + m_is_uninit = eLazyBoolCalculate; m_is_ptr = eLazyBoolCalculate; m_is_ref = eLazyBoolCalculate; m_is_aggregate = eLazyBoolCalculate; + m_is_instance_ptr = eLazyBoolCalculate; m_summary_formatter = {nullptr,false}; m_value.assign(""); m_summary.assign(""); m_error.assign(""); + m_val_summary_ok = false; + m_printed_instance_pointers = printed_instance_pointers ? printed_instance_pointers : InstancePointersSetSP(new InstancePointersSet()); } bool @@ -98,17 +99,15 @@ ValueObjectPrinter::PrintValueObject () PrintLocationIfNeeded(); m_stream->Indent(); - bool show_type = PrintTypeIfNeeded(); - - PrintNameIfNeeded(show_type); + PrintDecl(); } bool value_printed = false; bool summary_printed = false; - bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); + m_val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed); - if (val_summary_ok) + if (m_val_summary_ok) PrintChildrenIfNeeded (value_printed, summary_printed); else m_stream->EOL(); @@ -132,7 +131,7 @@ ValueObjectPrinter::GetMostSpecializedValue () { if (m_orig_valobj->IsDynamic()) { - if (options.m_use_dynamic == eNoDynamicValues) + if (m_options.m_use_dynamic == eNoDynamicValues) { ValueObject *static_value = m_orig_valobj->GetStaticValue().get(); if (static_value) @@ -145,9 +144,9 @@ ValueObjectPrinter::GetMostSpecializedValue () } else { - if (options.m_use_dynamic != eNoDynamicValues) + if (m_options.m_use_dynamic != eNoDynamicValues) { - ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get(); + ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(m_options.m_use_dynamic).get(); if (dynamic_value) m_valobj = dynamic_value; else @@ -159,7 +158,7 @@ ValueObjectPrinter::GetMostSpecializedValue () if (m_valobj->IsSynthetic()) { - if (options.m_use_synthetic == false) + if (m_options.m_use_synthetic == false) { ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get(); if (non_synthetic) @@ -168,7 +167,7 @@ ValueObjectPrinter::GetMostSpecializedValue () } else { - if (options.m_use_synthetic == true) + if (m_options.m_use_synthetic == true) { ValueObject *synthetic = m_valobj->GetSyntheticValue().get(); if (synthetic) @@ -176,8 +175,8 @@ ValueObjectPrinter::GetMostSpecializedValue () } } } - m_clang_type = m_valobj->GetClangType(); - m_type_flags = m_clang_type.GetTypeInfo (); + m_compiler_type = m_valobj->GetCompilerType(); + m_type_flags = m_compiler_type.GetTypeInfo (); return true; } @@ -195,9 +194,9 @@ ValueObjectPrinter::GetDescriptionForDisplay () const char* ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail) { - const char *root_valobj_name = options.m_root_valobj_name.empty() ? + const char *root_valobj_name = m_options.m_root_valobj_name.empty() ? m_valobj->GetName().AsCString() : - options.m_root_valobj_name.c_str(); + m_options.m_root_valobj_name.c_str(); return root_valobj_name ? root_valobj_name : if_fail; } @@ -205,7 +204,7 @@ bool ValueObjectPrinter::ShouldPrintValueObject () { if (m_should_print == eLazyBoolCalculate) - m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; + m_should_print = (m_options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo; return m_should_print == eLazyBoolYes; } @@ -213,10 +212,18 @@ bool ValueObjectPrinter::IsNil () { if (m_is_nil == eLazyBoolCalculate) - m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo; + m_is_nil = m_valobj->IsNilReference() ? eLazyBoolYes : eLazyBoolNo; return m_is_nil == eLazyBoolYes; } +bool +ValueObjectPrinter::IsUninitialized () +{ + if (m_is_uninit == eLazyBoolCalculate) + m_is_uninit = m_valobj->IsUninitializedReference() ? eLazyBoolYes : eLazyBoolNo; + return m_is_uninit == eLazyBoolYes; +} + bool ValueObjectPrinter::IsPtr () { @@ -241,10 +248,21 @@ ValueObjectPrinter::IsAggregate () return m_is_aggregate == eLazyBoolYes; } +bool +ValueObjectPrinter::IsInstancePointer () +{ + // you need to do this check on the value's clang type + if (m_is_instance_ptr == eLazyBoolCalculate) + m_is_instance_ptr = (m_valobj->GetValue().GetCompilerType().GetTypeInfo() & eTypeInstanceIsPointer) != 0 ? eLazyBoolYes : eLazyBoolNo; + if ((eLazyBoolYes == m_is_instance_ptr) && m_valobj->IsBaseClass()) + m_is_instance_ptr = eLazyBoolNo; + return m_is_instance_ptr == eLazyBoolYes; +} + bool ValueObjectPrinter::PrintLocationIfNeeded () { - if (options.m_show_location) + if (m_options.m_show_location) { m_stream->Printf("%s: ", m_valobj->GetLocationAsCString()); return true; @@ -252,88 +270,155 @@ ValueObjectPrinter::PrintLocationIfNeeded () return false; } -bool -ValueObjectPrinter::PrintTypeIfNeeded () +void +ValueObjectPrinter::PrintDecl () { bool show_type = true; // if we are at the root-level and been asked to hide the root's type, then hide it - if (m_curr_depth == 0 && options.m_hide_root_type) + if (m_curr_depth == 0 && m_options.m_hide_root_type) show_type = false; else // otherwise decide according to the usual rules (asked to show types - always at the root level) - show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output); + show_type = m_options.m_show_types || (m_curr_depth == 0 && !m_options.m_flat_output); + + StreamString typeName; + // always show the type at the root level if it is invalid if (show_type) { // Some ValueObjects don't have types (like registers sets). Only print // the type if there is one to print ConstString type_name; - if (options.m_use_type_display_name) - type_name = m_valobj->GetDisplayTypeName(); + if (m_compiler_type.IsValid()) + { + if (m_options.m_use_type_display_name) + type_name = m_valobj->GetDisplayTypeName(); + else + type_name = m_valobj->GetQualifiedTypeName(); + } else - type_name = m_valobj->GetQualifiedTypeName(); + { + // only show an invalid type name if the user explicitly triggered show_type + if (m_options.m_show_types) + type_name = ConstString(""); + else + type_name.Clear(); + } + if (type_name) - m_stream->Printf("(%s) ", type_name.GetCString()); - else - show_type = false; + { + std::string type_name_str(type_name.GetCString()); + if (m_options.m_hide_pointer_value) + { + for(auto iter = type_name_str.find(" *"); + iter != std::string::npos; + iter = type_name_str.find(" *")) + { + type_name_str.erase(iter, 2); + } + } + typeName.Printf("%s", type_name_str.c_str()); + } } - return show_type; -} - -bool -ValueObjectPrinter::PrintNameIfNeeded (bool show_type) -{ - if (options.m_flat_output) + + StreamString varName; + + if (m_options.m_flat_output) { // If we are showing types, also qualify the C++ base classes const bool qualify_cxx_base_classes = show_type; - if (!options.m_hide_name) + if (!m_options.m_hide_name) { - m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes); - m_stream->PutCString(" ="); - return true; + m_valobj->GetExpressionPath(varName, qualify_cxx_base_classes); } } - else if (!options.m_hide_name) + else if (!m_options.m_hide_name) { const char *name_cstr = GetRootNameForDisplay(""); - m_stream->Printf ("%s =", name_cstr); - return true; + varName.Printf ("%s", name_cstr); + } + + bool decl_printed = false; + if (!m_options.m_decl_printing_helper) + { + // if the user didn't give us a custom helper, pick one based upon the language, either the one that this printer is bound to, or the preferred one for the ValueObject + lldb::LanguageType lang_type = (m_options.m_varformat_language == lldb::eLanguageTypeUnknown) ? m_valobj->GetPreferredDisplayLanguage() : m_options.m_varformat_language; + if (Language *lang_plugin = Language::FindPlugin(lang_type)) + { + m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper(); + } + } + + if (m_options.m_decl_printing_helper) + { + ConstString type_name_cstr(typeName.GetData()); + ConstString var_name_cstr(varName.GetData()); + + StreamString dest_stream; + if (m_options.m_decl_printing_helper (type_name_cstr, + var_name_cstr, + m_options, + dest_stream)) + { + decl_printed = true; + m_stream->Printf("%s", dest_stream.GetData()); + } + } + + // if the helper failed, or there is none, do a default thing + if (!decl_printed) + { + if (typeName.GetSize()) + m_stream->Printf("(%s) ", typeName.GetData()); + if (varName.GetSize()) + m_stream->Printf("%s =", varName.GetData()); + else if (!m_options.m_hide_name) + m_stream->Printf(" ="); } - return false; } bool ValueObjectPrinter::CheckScopeIfNeeded () { - if (options.m_scope_already_checked) + if (m_options.m_scope_already_checked) return true; return m_valobj->IsInScope(); } TypeSummaryImpl* -ValueObjectPrinter::GetSummaryFormatter () +ValueObjectPrinter::GetSummaryFormatter (bool null_if_omitted) { if (m_summary_formatter.second == false) { - TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); + TypeSummaryImpl* entry = m_options.m_summary_sp ? m_options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get(); - if (options.m_omit_summary_depth > 0) + if (m_options.m_omit_summary_depth > 0) entry = NULL; m_summary_formatter.first = entry; m_summary_formatter.second = true; } + if (m_options.m_omit_summary_depth > 0 && null_if_omitted) + return nullptr; return m_summary_formatter.first; } +static bool +IsPointerValue (const CompilerType &type) +{ + Flags type_flags(type.GetTypeInfo()); + if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer)) + return type_flags.AllClear(eTypeIsBuiltIn); + return false; +} + void ValueObjectPrinter::GetValueSummaryError (std::string& value, std::string& summary, std::string& error) { - if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat()) + if (m_options.m_format != eFormatDefault && m_options.m_format != m_valobj->GetFormat()) { - m_valobj->GetValueAsCString(options.m_format, + m_valobj->GetValueAsCString(m_options.m_format, value); } else @@ -350,14 +435,16 @@ ValueObjectPrinter::GetValueSummaryError (std::string& value, { if (IsNil()) summary.assign("nil"); - else if (options.m_omit_summary_depth == 0) + else if (IsUninitialized()) + summary.assign(""); + else if (m_options.m_omit_summary_depth == 0) { TypeSummaryImpl* entry = GetSummaryFormatter(); if (entry) - m_valobj->GetSummaryAsCString(entry, summary); + m_valobj->GetSummaryAsCString(entry, summary, m_options.m_varformat_language); else { - const char* sum_cstr = m_valobj->GetSummaryAsCString(); + const char* sum_cstr = m_valobj->GetSummaryAsCString(m_options.m_varformat_language); if (sum_cstr) summary.assign(sum_cstr); } @@ -380,6 +467,16 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, } if (m_error.size()) { + // we need to support scenarios in which it is actually fine for a value to have no type + // but - on the other hand - if we get an error *AND* have no type, we try to get out + // gracefully, since most often that combination means "could not resolve a type" + // and the default failure mode is quite ugly + if (!m_compiler_type.IsValid()) + { + m_stream->Printf(" "); + return false; + } + error_printed = true; m_stream->Printf (" <%s>\n", m_error.c_str()); } @@ -390,10 +487,14 @@ ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed, // the value if this thing is nil // (but show the value if the user passes a format explicitly) TypeSummaryImpl* entry = GetSummaryFormatter(); - if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value) + if (!IsNil() && !IsUninitialized() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value) { - m_stream->Printf(" %s", m_value.c_str()); - value_printed = true; + if (m_options.m_hide_pointer_value && IsPointerValue(m_valobj->GetCompilerType())) {} + else + { + m_stream->Printf(" %s", m_value.c_str()); + value_printed = true; + } } if (m_summary.size()) @@ -413,9 +514,9 @@ ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, if (ShouldPrintValueObject()) { // let's avoid the overly verbose no description error for a nil thing - if (options.m_use_objc && !IsNil()) + if (m_options.m_use_objc && !IsNil() && !IsUninitialized()) { - if (!options.m_hide_value || !options.m_hide_name) + if (!m_options.m_hide_value || !m_options.m_hide_name) m_stream->Printf(" "); const char *object_desc = nullptr; if (value_printed || summary_printed) @@ -436,14 +537,62 @@ ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed, return true; } +bool +DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root, + TypeSummaryImpl* entry, + ValueObject *valobj, + const std::string& summary) +{ + switch (m_mode) + { + case Mode::Always: + return (m_count > 0); + case Mode::Never: + return false; + case Mode::Default: + if (is_root) + m_count = std::min(m_count,1); + return m_count > 0; + case Mode::Formatters: + if (!entry || entry->DoesPrintChildren(valobj) || summary.empty()) + return m_count > 0; + return false; + } + return false; +} + +bool +DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const +{ + switch (m_mode) + { + case Mode::Always: + case Mode::Default: + case Mode::Formatters: + return (m_count > 0); + case Mode::Never: + return false; + } + return false; +} + bool ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, - uint32_t& curr_ptr_depth) + DumpValueObjectOptions::PointerDepth& curr_ptr_depth) { const bool is_ref = IsRef (); const bool is_ptr = IsPtr (); - - if (is_failed_description || m_curr_depth < options.m_max_depth) + const bool is_uninit = IsUninitialized(); + + if (is_uninit) + return false; + + TypeSummaryImpl* entry = GetSummaryFormatter(); + + if (m_options.m_use_objc) + return false; + + if (is_failed_description || m_curr_depth < m_options.m_max_depth) { // We will show children for all concrete types. We won't show // pointer contents unless a pointer depth has been specified. @@ -461,25 +610,37 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description, if (m_valobj->GetPointerValue (&ptr_address_type) == 0) return false; - else if (is_ref && m_curr_depth == 0 && curr_ptr_depth == 0) + const bool is_root_level = m_curr_depth == 0; + + if (is_ref && + is_root_level) { // If this is the root object (depth is zero) that we are showing // and it is a reference, and no pointer depth has been supplied // print out what it references. Don't do this at deeper depths // otherwise we can end up with infinite recursion... - curr_ptr_depth = 1; + return true; } - return (curr_ptr_depth > 0); + return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary); } - TypeSummaryImpl* entry = GetSummaryFormatter(); - return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty()); } return false; } +bool +ValueObjectPrinter::ShouldExpandEmptyAggregates () +{ + TypeSummaryImpl* entry = GetSummaryFormatter(); + + if (!entry) + return true; + + return entry->DoesPrintEmptyAggregates(); +} + ValueObject* ValueObjectPrinter::GetValueObjectForChildrenGeneration () { @@ -489,7 +650,7 @@ ValueObjectPrinter::GetValueObjectForChildrenGeneration () void ValueObjectPrinter::PrintChildrenPreamble () { - if (options.m_flat_output) + if (m_options.m_flat_output) { if (ShouldPrintValueObject()) m_stream->EOL(); @@ -504,22 +665,23 @@ ValueObjectPrinter::PrintChildrenPreamble () void ValueObjectPrinter::PrintChild (ValueObjectSP child_sp, - uint32_t curr_ptr_depth) + const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) { - DumpValueObjectOptions child_options(options); - child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); - child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) + DumpValueObjectOptions child_options(m_options); + child_options.SetFormat(m_options.m_format).SetSummary().SetRootValueObjectName(); + child_options.SetScopeChecked(true).SetHideName(m_options.m_hide_name).SetHideValue(m_options.m_hide_value) .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); + if (child_sp.get()) { ValueObjectPrinter child_printer(child_sp.get(), m_stream, child_options, - (IsPtr() || IsRef()) && curr_ptr_depth >= 1 ? curr_ptr_depth - 1 : curr_ptr_depth, - m_curr_depth + 1); + (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth, + m_curr_depth + 1, + m_printed_instance_pointers); child_printer.PrintValueObject(); } - } uint32_t @@ -533,7 +695,7 @@ ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) { const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - if (num_children > max_num_children && !options.m_ignore_cap) + if (num_children > max_num_children && !m_options.m_ignore_cap) { print_dotdotdot = true; return max_num_children; @@ -545,7 +707,7 @@ ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot) void ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) { - if (!options.m_flat_output) + if (!m_options.m_flat_output) { if (print_dotdotdot) { @@ -557,8 +719,34 @@ ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot) } } +bool +ValueObjectPrinter::ShouldPrintEmptyBrackets (bool value_printed, + bool summary_printed) +{ + ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); + + if (!IsAggregate()) + return false; + + if (m_options.m_reveal_empty_aggregates == false) + { + if (value_printed || summary_printed) + return false; + } + + if (synth_m_valobj->MightHaveChildren()) + return true; + + if (m_val_summary_ok) + return false; + + return true; +} + void -ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) +ValueObjectPrinter::PrintChildren (bool value_printed, + bool summary_printed, + const DumpValueObjectOptions::PointerDepth& curr_ptr_depth) { ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration(); @@ -566,23 +754,44 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth) size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot); if (num_children) { - PrintChildrenPreamble (); + bool any_children_printed = false; for (size_t idx=0; idxGetChildAtIndex(idx, true)); - PrintChild (child_sp, curr_ptr_depth); + if (child_sp) + { + if (!any_children_printed) + { + PrintChildrenPreamble (); + any_children_printed = true; + } + PrintChild (child_sp, curr_ptr_depth); + } } - PrintChildrenPostamble (print_dotdotdot); + if (any_children_printed) + PrintChildrenPostamble (print_dotdotdot); + else + { + if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) + { + if (ShouldPrintValueObject()) + m_stream->PutCString(" {}\n"); + else + m_stream->EOL(); + } + else + m_stream->EOL(); + } } - else if (IsAggregate()) + else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) { // Aggregate, no children... if (ShouldPrintValueObject()) { // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value - if (m_valobj->DoesProvideSyntheticValue()) + if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates()) m_stream->PutCString( "\n"); else m_stream->PutCString(" {}\n"); @@ -614,7 +823,7 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) { lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true)); if (child_sp) - child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic); + child_sp = child_sp->GetQualifiedRepresentationIfAvailable(m_options.m_use_dynamic, m_options.m_use_synthetic); if (child_sp) { if (idx) @@ -630,7 +839,7 @@ ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names) } child_sp->DumpPrintableRepresentation(*m_stream, ValueObject::eValueObjectRepresentationStyleSummary, - lldb::eFormatInvalid, + m_options.m_format, ValueObject::ePrintableRepresentationSpecialCasesDisable); } } @@ -651,13 +860,30 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, // if that happens, we want to display the children, if any bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed); - uint32_t curr_ptr_depth = m_ptr_depth; + auto curr_ptr_depth = m_ptr_depth; bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth); - bool print_oneline = (curr_ptr_depth > 0 || - options.m_show_types || - !options.m_allow_oneliner_mode || - options.m_flat_output || - options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); + bool print_oneline = (curr_ptr_depth.CanAllowExpansion() || + m_options.m_show_types || + !m_options.m_allow_oneliner_mode || + m_options.m_flat_output || + m_options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj); + bool is_instance_ptr = IsInstancePointer(); + uint64_t instance_ptr_value = LLDB_INVALID_ADDRESS; + + if (print_children && is_instance_ptr) + { + instance_ptr_value = m_valobj->GetValueAsUnsigned(0); + if (m_printed_instance_pointers->count(instance_ptr_value)) + { + // we already printed this instance-is-pointer thing, so don't expand it + m_stream->PutCString(" {...}\n"); + + // we're done here - get out fast + return; + } + else + m_printed_instance_pointers->emplace(instance_ptr_value); // remember this guy for future reference + } if (print_children) { @@ -668,11 +894,11 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, m_stream->EOL(); } else - PrintChildren (curr_ptr_depth); + PrintChildren (value_printed, summary_printed, curr_ptr_depth); } - else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) + else if (m_curr_depth >= m_options.m_max_depth && IsAggregate() && ShouldPrintValueObject()) { - m_stream->PutCString("{...}\n"); + m_stream->PutCString("{...}\n"); } else m_stream->EOL(); @@ -681,7 +907,7 @@ ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed, bool ValueObjectPrinter::ShouldPrintValidation () { - return options.m_run_validator; + return m_options.m_run_validator; } bool diff --git a/source/DataFormatters/VectorType.cpp b/source/DataFormatters/VectorType.cpp index 316d7b540bcd..347afa5c0559 100644 --- a/source/DataFormatters/VectorType.cpp +++ b/source/DataFormatters/VectorType.cpp @@ -1,4 +1,4 @@ -//===-- VectorType.cpp ---------------------------------------------*- C++ -*-===// +//===-- VectorType.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,17 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/DataFormatters/VectorType.h" #include "lldb/Core/ValueObject.h" -#include "lldb/DataFormatters/CXXFormatterFunctions.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" @@ -20,87 +25,87 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; -static ClangASTType -GetClangTypeForFormat (lldb::Format format, - ClangASTType element_type, - ClangASTContext *ast_ctx) +static CompilerType +GetCompilerTypeForFormat (lldb::Format format, + CompilerType element_type, + TypeSystem *type_system) { - lldbassert(ast_ctx && "ast_ctx needs to be not NULL"); + lldbassert(type_system && "type_system needs to be not NULL"); switch (format) { case lldb::eFormatAddressInfo: case lldb::eFormatPointer: - return ast_ctx->GetPointerSizedIntType(false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8*type_system->GetPointerByteSize()); case lldb::eFormatBoolean: - return ast_ctx->GetBasicType(lldb::eBasicTypeBool); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeBool); case lldb::eFormatBytes: case lldb::eFormatBytesWithASCII: case lldb::eFormatChar: case lldb::eFormatCharArray: case lldb::eFormatCharPrintable: - return ast_ctx->GetBasicType(lldb::eBasicTypeChar); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); case lldb::eFormatComplex /* lldb::eFormatComplexFloat */: - return ast_ctx->GetBasicType(lldb::eBasicTypeFloatComplex); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloatComplex); case lldb::eFormatCString: - return ast_ctx->GetBasicType(lldb::eBasicTypeChar).GetPointerType(); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar).GetPointerType(); case lldb::eFormatFloat: - return ast_ctx->GetBasicType(lldb::eBasicTypeFloat); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); case lldb::eFormatHex: case lldb::eFormatHexUppercase: case lldb::eFormatOctal: - return ast_ctx->GetBasicType(lldb::eBasicTypeInt); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeInt); case lldb::eFormatHexFloat: - return ast_ctx->GetBasicType(lldb::eBasicTypeFloat); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeFloat); case lldb::eFormatUnicode16: case lldb::eFormatUnicode32: case lldb::eFormatUnsigned: - return ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedInt); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt); case lldb::eFormatVectorOfChar: - return ast_ctx->GetBasicType(lldb::eBasicTypeChar); + return type_system->GetBasicTypeFromAST(lldb::eBasicTypeChar); case lldb::eFormatVectorOfFloat32: - return ast_ctx->GetFloatTypeFromBitSize(32); + return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 32); case lldb::eFormatVectorOfFloat64: - return ast_ctx->GetFloatTypeFromBitSize(64); + return type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingIEEE754, 64); case lldb::eFormatVectorOfSInt16: - return ast_ctx->GetIntTypeFromBitSize(16, true); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 16); case lldb::eFormatVectorOfSInt32: - return ast_ctx->GetIntTypeFromBitSize(32, true); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 32); case lldb::eFormatVectorOfSInt64: - return ast_ctx->GetIntTypeFromBitSize(64, true); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 64); case lldb::eFormatVectorOfSInt8: - return ast_ctx->GetIntTypeFromBitSize(8, true); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingSint, 8); case lldb::eFormatVectorOfUInt128: - return ast_ctx->GetIntTypeFromBitSize(128, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 128); case lldb::eFormatVectorOfUInt16: - return ast_ctx->GetIntTypeFromBitSize(16, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 16); case lldb::eFormatVectorOfUInt32: - return ast_ctx->GetIntTypeFromBitSize(32, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 32); case lldb::eFormatVectorOfUInt64: - return ast_ctx->GetIntTypeFromBitSize(64, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 64); case lldb::eFormatVectorOfUInt8: - return ast_ctx->GetIntTypeFromBitSize(8, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8); case lldb::eFormatDefault: return element_type; @@ -113,13 +118,13 @@ GetClangTypeForFormat (lldb::Format format, case lldb::eFormatOSType: case lldb::eFormatVoid: default: - return ast_ctx->GetIntTypeFromBitSize(8, false); + return type_system->GetBuiltinTypeForEncodingAndBitSize (eEncodingUint, 8); } } static lldb::Format GetItemFormatForFormat (lldb::Format format, - ClangASTType element_type) + CompilerType element_type) { switch (format) { @@ -169,8 +174,8 @@ GetItemFormatForFormat (lldb::Format format, } static size_t -CalculateNumChildren (ClangASTType container_type, - ClangASTType element_type, +CalculateNumChildren (CompilerType container_type, + CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope = nullptr // does not matter here because all we trade in are basic types ) { @@ -199,15 +204,17 @@ namespace lldb_private { m_child_type(), m_num_children(0) {} - - virtual size_t - CalculateNumChildren () + + ~VectorTypeSyntheticFrontEnd() override = default; + + size_t + CalculateNumChildren() override { return m_num_children; } - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx) + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -225,29 +232,32 @@ namespace lldb_private { return child_sp; } - virtual bool - Update() + bool + Update() override { m_parent_format = m_backend.GetFormat(); - ClangASTType parent_type(m_backend.GetClangType()); - ClangASTType element_type; + CompilerType parent_type(m_backend.GetCompilerType()); + CompilerType element_type; parent_type.IsVectorType(&element_type, nullptr); - m_child_type = ::GetClangTypeForFormat(m_parent_format, element_type, ClangASTContext::GetASTContext(parent_type.GetASTContext())); + TargetSP target_sp(m_backend.GetTargetSP()); + m_child_type = ::GetCompilerTypeForFormat(m_parent_format, + element_type, + target_sp ? target_sp->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC) : nullptr); m_num_children = ::CalculateNumChildren(parent_type, m_child_type); m_item_format = GetItemFormatForFormat(m_parent_format, m_child_type); return false; } - - virtual bool - MightHaveChildren () + + bool + MightHaveChildren() override { return true; } - - virtual size_t - GetIndexOfChildWithName (const ConstString &name) + + size_t + GetIndexOfChildWithName(const ConstString &name) override { const char* item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -255,18 +265,16 @@ namespace lldb_private { return UINT32_MAX; return idx; } - - virtual - ~VectorTypeSyntheticFrontEnd () {} - + private: lldb::Format m_parent_format; lldb::Format m_item_format; - ClangASTType m_child_type; + CompilerType m_child_type; size_t m_num_children; }; - } -} + + } // namespace formatters +} // namespace lldb_private bool lldb_private::formatters::VectorTypeSummaryProvider (ValueObject& valobj, @@ -317,6 +325,6 @@ lldb_private::SyntheticChildrenFrontEnd* lldb_private::formatters::VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { if (!valobj_sp) - return NULL; - return (new VectorTypeSyntheticFrontEnd(valobj_sp)); + return nullptr; + return new VectorTypeSyntheticFrontEnd(valobj_sp); } diff --git a/source/Expression/ASTDumper.cpp b/source/Expression/ASTDumper.cpp deleted file mode 100644 index 5210d149e666..000000000000 --- a/source/Expression/ASTDumper.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Log.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Symbol/ClangASTType.h" - -#include "llvm/Support/raw_ostream.h" - -using namespace lldb_private; - -ASTDumper::ASTDumper (clang::Decl *decl) -{ - clang::DeclContext *decl_ctx = llvm::dyn_cast(decl); - - bool has_external_lexical_storage; - bool has_external_visible_storage; - - if (decl_ctx) - { - has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - decl_ctx->setHasExternalLexicalStorage(false); - decl_ctx->setHasExternalVisibleStorage(false); - } - - llvm::raw_string_ostream os(m_dump); - decl->print (os); - os.flush(); - - if (decl_ctx) - { - decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); - decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); - } -} - -ASTDumper::ASTDumper (clang::DeclContext *decl_ctx) -{ - bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); - bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); - - decl_ctx->setHasExternalLexicalStorage(false); - decl_ctx->setHasExternalVisibleStorage(false); - - if (clang::Decl *decl = llvm::dyn_cast(decl_ctx)) - { - llvm::raw_string_ostream os(m_dump); - decl->print (os); - os.flush(); - } - else - { - m_dump.assign(""); - } - - decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); - decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); -} - -ASTDumper::ASTDumper (const clang::Type *type) -{ - m_dump = clang::QualType(type, 0).getAsString(); -} - -ASTDumper::ASTDumper (clang::QualType type) -{ - m_dump = type.getAsString(); -} - -ASTDumper::ASTDumper (lldb::clang_type_t type) -{ - m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); -} - -ASTDumper::ASTDumper (const ClangASTType &clang_type) -{ - m_dump = clang_type.GetQualType().getAsString(); -} - - -const char * -ASTDumper::GetCString() -{ - return m_dump.c_str(); -} - -void ASTDumper::ToSTDERR() -{ - fprintf(stderr, "%s\n", m_dump.c_str()); -} - -void ASTDumper::ToLog(Log *log, const char *prefix) -{ - size_t len = m_dump.length() + 1; - - char *alloc = (char*)malloc(len); - char *str = alloc; - - memcpy(str, m_dump.c_str(), len); - - char *end = NULL; - - end = strchr(str, '\n'); - - while (end) - { - *end = '\0'; - - log->Printf("%s%s", prefix, str); - - *end = '\n'; - - str = end + 1; - end = strchr(str, '\n'); - } - - log->Printf("%s%s", prefix, str); - - free(alloc); -} - -void ASTDumper::ToStream(lldb::StreamSP &stream) -{ - stream->PutCString(m_dump.c_str()); -} diff --git a/source/Expression/ASTResultSynthesizer.cpp b/source/Expression/ASTResultSynthesizer.cpp deleted file mode 100644 index c3d42cb49ec5..000000000000 --- a/source/Expression/ASTResultSynthesizer.cpp +++ /dev/null @@ -1,512 +0,0 @@ -//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "stdlib.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Stmt.h" -#include "clang/Parse/Parser.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" -#include "lldb/Core/Log.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ASTResultSynthesizer.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTImporter.h" -#include "lldb/Target/Target.h" - -using namespace llvm; -using namespace clang; -using namespace lldb_private; - -ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, - Target &target) : - m_ast_context (NULL), - m_passthrough (passthrough), - m_passthrough_sema (NULL), - m_target (target), - m_sema (NULL) -{ - if (!m_passthrough) - return; - - m_passthrough_sema = dyn_cast(passthrough); -} - -ASTResultSynthesizer::~ASTResultSynthesizer() -{ -} - -void -ASTResultSynthesizer::Initialize(ASTContext &Context) -{ - m_ast_context = &Context; - - if (m_passthrough) - m_passthrough->Initialize(Context); -} - -void -ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (NamedDecl *named_decl = dyn_cast(D)) - { - if (log && log->GetVerbose()) - { - if (named_decl->getIdentifier()) - log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart()); - else if (ObjCMethodDecl *method_decl = dyn_cast(D)) - log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str()); - else - log->Printf("TransformTopLevelDecl()"); - } - - } - - if (LinkageSpecDecl *linkage_spec_decl = dyn_cast(D)) - { - RecordDecl::decl_iterator decl_iterator; - - for (decl_iterator = linkage_spec_decl->decls_begin(); - decl_iterator != linkage_spec_decl->decls_end(); - ++decl_iterator) - { - TransformTopLevelDecl(*decl_iterator); - } - } - else if (ObjCMethodDecl *method_decl = dyn_cast(D)) - { - if (m_ast_context && - !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) - { - RecordPersistentTypes(method_decl); - SynthesizeObjCMethodResult(method_decl); - } - } - else if (FunctionDecl *function_decl = dyn_cast(D)) - { - if (m_ast_context && - !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) - { - RecordPersistentTypes(function_decl); - SynthesizeFunctionResult(function_decl); - } - } -} - -bool -ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) -{ - DeclGroupRef::iterator decl_iterator; - - for (decl_iterator = D.begin(); - decl_iterator != D.end(); - ++decl_iterator) - { - Decl *decl = *decl_iterator; - - TransformTopLevelDecl(decl); - } - - if (m_passthrough) - return m_passthrough->HandleTopLevelDecl(D); - return true; -} - -bool -ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_sema) - return false; - - FunctionDecl *function_decl = FunDecl; - - if (!function_decl) - return false; - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); - - function_decl->print(os); - - os.flush(); - - log->Printf ("Untransformed function AST:\n%s", s.c_str()); - } - - Stmt *function_body = function_decl->getBody(); - CompoundStmt *compound_stmt = dyn_cast(function_body); - - bool ret = SynthesizeBodyResult (compound_stmt, - function_decl); - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); - - function_decl->print(os); - - os.flush(); - - log->Printf ("Transformed function AST:\n%s", s.c_str()); - } - - return ret; -} - -bool -ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_sema) - return false; - - if (!MethodDecl) - return false; - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); - - MethodDecl->print(os); - - os.flush(); - - log->Printf ("Untransformed method AST:\n%s", s.c_str()); - } - - Stmt *method_body = MethodDecl->getBody(); - - if (!method_body) - return false; - - CompoundStmt *compound_stmt = dyn_cast(method_body); - - bool ret = SynthesizeBodyResult (compound_stmt, - MethodDecl); - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream os(s); - - MethodDecl->print(os); - - os.flush(); - - log->Printf("Transformed method AST:\n%s", s.c_str()); - } - - return ret; -} - -bool -ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, - DeclContext *DC) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ASTContext &Ctx(*m_ast_context); - - if (!Body) - return false; - - if (Body->body_empty()) - return false; - - Stmt **last_stmt_ptr = Body->body_end() - 1; - Stmt *last_stmt = *last_stmt_ptr; - - while (dyn_cast(last_stmt)) - { - if (last_stmt_ptr != Body->body_begin()) - { - last_stmt_ptr--; - last_stmt = *last_stmt_ptr; - } - else - { - return false; - } - } - - Expr *last_expr = dyn_cast(last_stmt); - - if (!last_expr) - // No auxiliary variable necessary; expression returns void - return true; - - // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the - // case. - - do { - ImplicitCastExpr *implicit_cast = dyn_cast(last_expr); - - if (!implicit_cast) - break; - - if (implicit_cast->getCastKind() != CK_LValueToRValue) - break; - - last_expr = implicit_cast->getSubExpr(); - } while (0); - - // is_lvalue is used to record whether the expression returns an assignable Lvalue or an - // Rvalue. This is relevant because they are handled differently. - // - // For Lvalues - // - // - In AST result synthesis (here!) the expression E is transformed into an initialization - // T *$__lldb_expr_result_ptr = &E. - // - // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be - // passed into the expression. - // - // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at - // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent - // variables are treated similarly, having been materialized as references, but in those - // cases the value of the reference itself is never modified.) - // - // - During materialization, $0 (the result persistent variable) is ignored. - // - // - During dematerialization, $0 is marked up as a load address with value equal to the - // contents of the structure entry. - // - // For Rvalues - // - // - In AST result synthesis the expression E is transformed into an initialization - // static T $__lldb_expr_result = E. - // - // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be - // passed into the expression. - // - // - In IR transformations, an instruction is inserted at the beginning of the function to - // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result - // are redirected at that dereferenced version. Guard variables for the static variable - // are excised. - // - // - During materialization, $0 (the result persistent variable) is populated with the location - // of a newly-allocated area of memory. - // - // - During dematerialization, $0 is ignored. - - bool is_lvalue = - (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) && - (last_expr->getObjectKind() == OK_Ordinary); - - QualType expr_qual_type = last_expr->getType(); - const clang::Type *expr_type = expr_qual_type.getTypePtr(); - - if (!expr_type) - return false; - - if (expr_type->isVoidType()) - return true; - - if (log) - { - std::string s = expr_qual_type.getAsString(); - - log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); - } - - clang::VarDecl *result_decl = NULL; - - if (is_lvalue) - { - IdentifierInfo *result_ptr_id; - - if (expr_type->isFunctionType()) - result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers - else - result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); - - m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type); - - QualType ptr_qual_type; - - if (expr_qual_type->getAs() != NULL) - ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); - else - ptr_qual_type = Ctx.getPointerType(expr_qual_type); - - result_decl = VarDecl::Create(Ctx, - DC, - SourceLocation(), - SourceLocation(), - result_ptr_id, - ptr_qual_type, - NULL, - SC_Static); - - if (!result_decl) - return false; - - ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); - - m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); - } - else - { - IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); - - result_decl = VarDecl::Create(Ctx, - DC, - SourceLocation(), - SourceLocation(), - &result_id, - expr_qual_type, - NULL, - SC_Static); - - if (!result_decl) - return false; - - m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); - } - - DC->addDecl(result_decl); - - /////////////////////////////// - // call AddInitializerToDecl - // - - //m_sema->AddInitializerToDecl(result_decl, last_expr); - - ///////////////////////////////// - // call ConvertDeclToDeclGroup - // - - Sema::DeclGroupPtrTy result_decl_group_ptr; - - result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); - - //////////////////////// - // call ActOnDeclStmt - // - - StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr, - SourceLocation(), - SourceLocation())); - - //////////////////////////////////////////////// - // replace the old statement with the new one - // - - *last_stmt_ptr = reinterpret_cast(result_initialization_stmt_result.get()); - - return true; -} - -void -ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) -{ - if (m_passthrough) - m_passthrough->HandleTranslationUnit(Ctx); -} - -void -ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) -{ - typedef DeclContext::specific_decl_iterator TypeDeclIterator; - - for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), - e = TypeDeclIterator(FunDeclCtx->decls_end()); - i != e; - ++i) - { - MaybeRecordPersistentType(*i); - } -} - -void -ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) -{ - if (!D->getIdentifier()) - return; - - StringRef name = D->getName(); - - if (name.size() == 0 || name[0] != '$') - return; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ConstString name_cs(name.str().c_str()); - - if (log) - log->Printf ("Recording persistent type %s\n", name_cs.GetCString()); - - Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(), - m_ast_context, - D); - - if (TypeDecl *TypeDecl_scratch = dyn_cast(D_scratch)) - m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch); -} - -void -ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) -{ - if (m_passthrough) - m_passthrough->HandleTagDeclDefinition(D); -} - -void -ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) -{ - if (m_passthrough) - m_passthrough->CompleteTentativeDefinition(D); -} - -void -ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) -{ - if (m_passthrough) - m_passthrough->HandleVTable(RD); -} - -void -ASTResultSynthesizer::PrintStats() -{ - if (m_passthrough) - m_passthrough->PrintStats(); -} - -void -ASTResultSynthesizer::InitializeSema(Sema &S) -{ - m_sema = &S; - - if (m_passthrough_sema) - m_passthrough_sema->InitializeSema(S); -} - -void -ASTResultSynthesizer::ForgetSema() -{ - m_sema = NULL; - - if (m_passthrough_sema) - m_passthrough_sema->ForgetSema(); -} diff --git a/source/Expression/ASTStructExtractor.cpp b/source/Expression/ASTStructExtractor.cpp deleted file mode 100644 index 98628dbc92be..000000000000 --- a/source/Expression/ASTStructExtractor.cpp +++ /dev/null @@ -1,220 +0,0 @@ -//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "stdlib.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/Expr.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/Stmt.h" -#include "clang/Parse/Parser.h" -#include "clang/Sema/Sema.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" -#include "lldb/Core/Log.h" -#include "lldb/Expression/ASTStructExtractor.h" - -using namespace llvm; -using namespace clang; -using namespace lldb_private; - -ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, - const char *struct_name, - ClangFunction &function) : - m_ast_context (NULL), - m_passthrough (passthrough), - m_passthrough_sema (NULL), - m_sema (NULL), - m_action (NULL), - m_function (function), - m_struct_name (struct_name) -{ - if (!m_passthrough) - return; - - m_passthrough_sema = dyn_cast(passthrough); -} - -ASTStructExtractor::~ASTStructExtractor() -{ -} - -void -ASTStructExtractor::Initialize(ASTContext &Context) -{ - m_ast_context = &Context; - - if (m_passthrough) - m_passthrough->Initialize(Context); -} - -void -ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) -{ - if (!F->hasBody()) - return; - - Stmt *body_stmt = F->getBody(); - CompoundStmt *body_compound_stmt = dyn_cast(body_stmt); - - if (!body_compound_stmt) - return; // do we have to handle this? - - RecordDecl *struct_decl = NULL; - - StringRef desired_name(m_struct_name.c_str()); - - for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); - bi != be; - ++bi) - { - Stmt *curr_stmt = *bi; - DeclStmt *curr_decl_stmt = dyn_cast(curr_stmt); - if (!curr_decl_stmt) - continue; - DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); - for (Decl *candidate_decl : decl_group) - { - RecordDecl *candidate_record_decl = dyn_cast(candidate_decl); - if (!candidate_record_decl) - continue; - if (candidate_record_decl->getName() == desired_name) - { - struct_decl = candidate_record_decl; - break; - } - } - if (struct_decl) - break; - } - - if (!struct_decl) - return; - - const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); - - if (!struct_layout) - return; - - m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits - m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; - m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; - - for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); - field_index < num_fields; - ++field_index) - { - m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); - } - - m_function.m_struct_valid = true; -} - -void -ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) -{ - LinkageSpecDecl *linkage_spec_decl = dyn_cast(D); - - if (linkage_spec_decl) - { - RecordDecl::decl_iterator decl_iterator; - - for (decl_iterator = linkage_spec_decl->decls_begin(); - decl_iterator != linkage_spec_decl->decls_end(); - ++decl_iterator) - { - ExtractFromTopLevelDecl(*decl_iterator); - } - } - - FunctionDecl *function_decl = dyn_cast(D); - - if (m_ast_context && - function_decl && - !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) - { - ExtractFromFunctionDecl(function_decl); - } -} - -bool -ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) -{ - DeclGroupRef::iterator decl_iterator; - - for (decl_iterator = D.begin(); - decl_iterator != D.end(); - ++decl_iterator) - { - Decl *decl = *decl_iterator; - - ExtractFromTopLevelDecl(decl); - } - - if (m_passthrough) - return m_passthrough->HandleTopLevelDecl(D); - return true; -} - -void -ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) -{ - if (m_passthrough) - m_passthrough->HandleTranslationUnit(Ctx); -} - -void -ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) -{ - if (m_passthrough) - m_passthrough->HandleTagDeclDefinition(D); -} - -void -ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) -{ - if (m_passthrough) - m_passthrough->CompleteTentativeDefinition(D); -} - -void -ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) -{ - if (m_passthrough) - m_passthrough->HandleVTable(RD); -} - -void -ASTStructExtractor::PrintStats() -{ - if (m_passthrough) - m_passthrough->PrintStats(); -} - -void -ASTStructExtractor::InitializeSema(Sema &S) -{ - m_sema = &S; - m_action = reinterpret_cast(m_sema); - - if (m_passthrough_sema) - m_passthrough_sema->InitializeSema(S); -} - -void -ASTStructExtractor::ForgetSema() -{ - m_sema = NULL; - m_action = NULL; - - if (m_passthrough_sema) - m_passthrough_sema->ForgetSema(); -} diff --git a/source/Expression/ClangASTSource.cpp b/source/Expression/ClangASTSource.cpp deleted file mode 100644 index 3988cd674afd..000000000000 --- a/source/Expression/ClangASTSource.cpp +++ /dev/null @@ -1,2075 +0,0 @@ -//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#include "clang/AST/ASTContext.h" -#include "clang/AST/RecordLayout.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Symbol/TaggedASTType.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Target.h" - -#include - -using namespace clang; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Scoped class that will remove an active lexical decl from the set -// when it goes out of scope. -//------------------------------------------------------------------ -namespace { - class ScopedLexicalDeclEraser - { - public: - ScopedLexicalDeclEraser(std::set &decls, - const clang::Decl *decl) - : m_active_lexical_decls(decls), m_decl(decl) - { - } - - ~ScopedLexicalDeclEraser() - { - m_active_lexical_decls.erase(m_decl); - } - - private: - std::set &m_active_lexical_decls; - const clang::Decl *m_decl; - }; -} - -ClangASTSource::~ClangASTSource() -{ - m_ast_importer->ForgetDestination(m_ast_context); - - // We are in the process of destruction, don't create clang ast context on demand - // by passing false to Target::GetScratchClangASTContext(create_on_demand). - ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); - - if (!scratch_clang_ast_context) - return; - - clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); - - if (!scratch_ast_context) - return; - - if (m_ast_context != scratch_ast_context) - m_ast_importer->ForgetSource(scratch_ast_context, m_ast_context); -} - -void -ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) -{ - if (!m_ast_context) - return; - - m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); - m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); -} - -// The core lookup interface. -bool -ClangASTSource::FindExternalVisibleDeclsByName -( - const DeclContext *decl_ctx, - DeclarationName clang_decl_name -) -{ - if (!m_ast_context) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - - if (GetImportInProgress()) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - - std::string decl_name (clang_decl_name.getAsString()); - -// if (m_decl_map.DoingASTImport ()) -// return DeclContext::lookup_result(); -// - switch (clang_decl_name.getNameKind()) { - // Normal identifiers. - case DeclarationName::Identifier: - { - clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo(); - - if (!identifier_info || - identifier_info->getBuiltinID() != 0) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - } - break; - - // Operator names. Not important for now. - case DeclarationName::CXXOperatorName: - case DeclarationName::CXXLiteralOperatorName: - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - // Using directives found in this context. - // Tell Sema we didn't find any or we'll end up getting asked a *lot*. - case DeclarationName::CXXUsingDirective: - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - { - llvm::SmallVector method_decls; - - NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx); - - FindObjCMethodDecls(method_search_context); - - SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls); - return (method_decls.size() > 0); - } - // These aren't possible in the global context. - case DeclarationName::CXXConstructorName: - case DeclarationName::CXXDestructorName: - case DeclarationName::CXXConversionFunctionName: - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - - - if (!GetLookupsEnabled()) - { - // Wait until we see a '$' at the start of a name before we start doing - // any lookups so we can avoid lookup up all of the builtin types. - if (!decl_name.empty() && decl_name[0] == '$') - { - SetLookupsEnabled (true); - } - else - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - } - - ConstString const_decl_name(decl_name.c_str()); - - const char *uniqued_const_decl_name = const_decl_name.GetCString(); - if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end()) - { - // We are currently looking up this name... - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - m_active_lookups.insert(uniqued_const_decl_name); -// static uint32_t g_depth = 0; -// ++g_depth; -// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name); - llvm::SmallVector name_decls; - NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx); - FindExternalVisibleDecls(name_search_context); - SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls); -// --g_depth; - m_active_lookups.erase (uniqued_const_decl_name); - return (name_decls.size() != 0); -} - -void -ClangASTSource::CompleteType (TagDecl *tag_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - if (log) - { - log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s", - current_id, static_cast(m_ast_context), - static_cast(tag_decl), - tag_decl->getName().str().c_str()); - - log->Printf(" CTD[%u] Before:", current_id); - ASTDumper dumper((Decl*)tag_decl); - dumper.ToLog(log, " [CTD] "); - } - - auto iter = m_active_lexical_decls.find(tag_decl); - if (iter != m_active_lexical_decls.end()) - return; - m_active_lexical_decls.insert(tag_decl); - ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); - - if (!m_ast_importer->CompleteTagDecl (tag_decl)) - { - // We couldn't complete the type. Maybe there's a definition - // somewhere else that can be completed. - - if (log) - log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id); - - bool found = false; - - DeclContext *decl_ctx = tag_decl->getDeclContext(); - - if (const NamespaceDecl *namespace_context = dyn_cast(decl_ctx)) - { - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context); - - if (log && log->GetVerbose()) - log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast(namespace_map.get()), - static_cast(namespace_map->size())); - - if (!namespace_map) - return; - - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e && !found; - ++i) - { - if (log) - log->Printf(" CTD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetNamespaceDecl()->getNameAsString().c_str(), - i->first->GetFileSpec().GetFilename().GetCString()); - - TypeList types; - - SymbolContext null_sc; - ConstString name(tag_decl->getName().str().c_str()); - - i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); - - for (uint32_t ti = 0, te = types.GetSize(); - ti != te && !found; - ++ti) - { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; - - ClangASTType clang_type (type->GetClangFullType()); - - if (!clang_type) - continue; - - const TagType *tag_type = clang_type.GetQualType()->getAs(); - - if (!tag_type) - continue; - - TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); - - if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) - found = true; - } - } - } - else - { - TypeList types; - - SymbolContext null_sc; - ConstString name(tag_decl->getName().str().c_str()); - ClangNamespaceDecl namespace_decl; - - const ModuleList &module_list = m_target->GetImages(); - - bool exact_match = false; - module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types); - - for (uint32_t ti = 0, te = types.GetSize(); - ti != te && !found; - ++ti) - { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; - - ClangASTType clang_type (type->GetClangFullType()); - - if (!clang_type) - continue; - - const TagType *tag_type = clang_type.GetQualType()->getAs(); - - if (!tag_type) - continue; - - TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); - - if (m_ast_importer->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) - found = true; - } - } - } - - if (log) - { - log->Printf(" [CTD] After:"); - ASTDumper dumper((Decl*)tag_decl); - dumper.ToLog(log, " [CTD] "); - } -} - -void -ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - { - log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", - static_cast(m_ast_context), - interface_decl->getName().str().c_str()); - log->Printf(" [COID] Before:"); - ASTDumper dumper((Decl*)interface_decl); - dumper.ToLog(log, " [COID] "); - } - - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; - - if (m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) - { - if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) - { - ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); - - if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) - { - m_ast_importer->SetDeclOrigin(interface_decl, original_iface_decl); - } - } - } - - m_ast_importer->CompleteObjCInterfaceDecl (interface_decl); - - if (interface_decl->getSuperClass() && - interface_decl->getSuperClass() != interface_decl) - CompleteType(interface_decl->getSuperClass()); - - if (log) - { - log->Printf(" [COID] After:"); - ASTDumper dumper((Decl*)interface_decl); - dumper.ToLog(log, " [COID] "); - } -} - -clang::ObjCInterfaceDecl * -ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl) -{ - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - return NULL; - - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - - if (!language_runtime) - return NULL; - - ConstString class_name(interface_decl->getNameAsString().c_str()); - - lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); - - if (!complete_type_sp) - return NULL; - - TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetClangFullType()); - lldb::clang_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); - - if (!complete_opaque_type) - return NULL; - - const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); - const ObjCInterfaceType *complete_interface_type = dyn_cast(complete_clang_type); - - if (!complete_interface_type) - return NULL; - - ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); - - return complete_iface_decl; -} - -clang::ExternalLoadResult -ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, - bool (*predicate)(Decl::Kind), - llvm::SmallVectorImpl &decls) -{ - ClangASTMetrics::RegisterLexicalQuery(); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - const Decl *context_decl = dyn_cast(decl_context); - - if (!context_decl) - return ELR_Failure; - - auto iter = m_active_lexical_decls.find(context_decl); - if (iter != m_active_lexical_decls.end()) - return ELR_Failure; - m_active_lexical_decls.insert(context_decl); - ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - if (log) - { - if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p with %s predicate", - current_id, static_cast(m_ast_context), - context_named_decl->getNameAsString().c_str(), - context_decl->getDeclKindName(), - static_cast(context_decl), - (predicate ? "non-null" : "null")); - else if(context_decl) - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p with %s predicate", - current_id, static_cast(m_ast_context), - context_decl->getDeclKindName(), - static_cast(context_decl), - (predicate ? "non-null" : "null")); - else - log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context with %s predicate", - current_id, static_cast(m_ast_context), - (predicate ? "non-null" : "null")); - } - - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; - - if (!m_ast_importer->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) - return ELR_Failure; - - if (log) - { - log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", - current_id, static_cast(original_ctx), - static_cast(original_decl)); - ASTDumper(original_decl).ToLog(log, " "); - } - - if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) - { - ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); - - if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) - { - original_decl = complete_iface_decl; - original_ctx = &complete_iface_decl->getASTContext(); - - m_ast_importer->SetDeclOrigin(context_decl, original_iface_decl); - } - } - - if (TagDecl *original_tag_decl = dyn_cast(original_decl)) - { - ExternalASTSource *external_source = original_ctx->getExternalSource(); - - if (external_source) - external_source->CompleteType (original_tag_decl); - } - - const DeclContext *original_decl_context = dyn_cast(original_decl); - - if (!original_decl_context) - return ELR_Failure; - - for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); - iter != original_decl_context->decls_end(); - ++iter) - { - Decl *decl = *iter; - - if (!predicate || predicate(decl->getKind())) - { - if (log) - { - ASTDumper ast_dumper(decl); - if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) - log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString()); - else - log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); - } - - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, original_ctx, decl); - - if (!copied_decl) - continue; - - if (FieldDecl *copied_field = dyn_cast(copied_decl)) - { - QualType copied_field_type = copied_field->getType(); - - m_ast_importer->RequireCompleteType(copied_field_type); - } - - decls.push_back(copied_decl); - - DeclContext *decl_context_non_const = const_cast(decl_context); - - if (copied_decl->getDeclContext() != decl_context) - { - if (copied_decl->getDeclContext()->containsDecl(copied_decl)) - copied_decl->getDeclContext()->removeDecl(copied_decl); - copied_decl->setDeclContext(decl_context_non_const); - } - - if (!decl_context_non_const->containsDecl(copied_decl)) - decl_context_non_const->addDeclInternal(copied_decl); - } - } - - return ELR_AlreadyLoaded; -} - -void -ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) -{ - assert (m_ast_context); - - ClangASTMetrics::RegisterVisibleQuery(); - - const ConstString name(context.m_decl_name.getAsString().c_str()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - if (log) - { - if (!context.m_decl_context) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", - current_id, static_cast(m_ast_context), - name.GetCString()); - else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", - current_id, static_cast(m_ast_context), - name.GetCString(), - context_named_decl->getNameAsString().c_str()); - else - log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", - current_id, static_cast(m_ast_context), - name.GetCString(), - context.m_decl_context->getDeclKindName()); - } - - context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); - - if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) - { - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context); - - if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", - current_id, static_cast(namespace_map.get()), - static_cast(namespace_map->size())); - - if (!namespace_map) - return; - - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e; - ++i) - { - if (log) - log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetNamespaceDecl()->getNameAsString().c_str(), - i->first->GetFileSpec().GetFilename().GetCString()); - - FindExternalVisibleDecls(context, - i->first, - i->second, - current_id); - } - } - else if (isa(context.m_decl_context)) - { - FindObjCPropertyAndIvarDecls(context); - } - else if (!isa(context.m_decl_context)) - { - // we shouldn't be getting FindExternalVisibleDecls calls for these - return; - } - else - { - ClangNamespaceDecl namespace_decl; - - if (log) - log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); - - FindExternalVisibleDecls(context, - lldb::ModuleSP(), - namespace_decl, - current_id); - } - - if (!context.m_namespace_map->empty()) - { - if (log && log->GetVerbose()) - log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", - current_id, - static_cast(context.m_namespace_map.get()), - static_cast(context.m_namespace_map->size())); - - NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); - - if (clang_namespace_decl) - clang_namespace_decl->setHasExternalVisibleStorage(); - } -} - -void -ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module_sp, - ClangNamespaceDecl &namespace_decl, - unsigned int current_id) -{ - assert (m_ast_context); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SymbolContextList sc_list; - - const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) - return; - - if (name_unique_cstr == NULL) - return; - - // The ClangASTSource is not responsible for finding $-names. - if (name_unique_cstr[0] == '$') - return; - - if (module_sp && namespace_decl) - { - ClangNamespaceDecl found_namespace_decl; - - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - - if (symbol_vendor) - { - SymbolContext null_sc; - - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); - - if (found_namespace_decl) - { - context.m_namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); - - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); - } - } - } - else - { - const ModuleList &target_images = m_target->GetImages(); - Mutex::Locker modules_locker (target_images.GetMutex()); - - for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) - { - lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); - - if (!image) - continue; - - ClangNamespaceDecl found_namespace_decl; - - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); - - if (!symbol_vendor) - continue; - - SymbolContext null_sc; - - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); - - if (found_namespace_decl) - { - context.m_namespace_map->push_back(std::pair(image, found_namespace_decl)); - - if (log) - log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); - } - } - } - - do - { - TypeList types; - SymbolContext null_sc; - const bool exact_match = false; - - if (module_sp && namespace_decl) - module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); - else - m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); - - bool found_a_type = false; - - if (types.GetSize()) - { - lldb::TypeSP type_sp = types.GetTypeAtIndex(0); - - if (log) - { - const char *name_string = type_sp->GetName().GetCString(); - - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", - current_id, - name.GetCString(), - (name_string ? name_string : "")); - } - - ClangASTType full_type = type_sp->GetClangFullType(); - - ClangASTType copied_clang_type (GuardedCopyType(full_type)); - - if (!copied_clang_type) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type", - current_id); - - break; - } - - context.AddTypeDecl(copied_clang_type); - - found_a_type = true; - } - - if (!found_a_type) - { - // Try the modules next. - - do - { - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!modules_decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::NamedDecl *const decl_from_modules = decls[0]; - - if (llvm::isa(decl_from_modules) || - llvm::isa(decl_from_modules) || - llvm::isa(decl_from_modules)) - { - clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; - - if (!copied_named_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules", - current_id); - - break; - } - - context.AddNamedDecl(copied_named_decl); - - found_a_type = true; - } - } - } while (0); - } - - if (!found_a_type) - { - do - { - // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists. - - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - break; - - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - - if (!language_runtime) - break; - - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - - if (!decl_vendor) - break; - - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); - clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; - - if (!copied_named_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", - current_id); - - break; - } - - context.AddNamedDecl(copied_named_decl); - } - while(0); - } - - } while(0); -} - -template class TaggedASTDecl { -public: - TaggedASTDecl() : decl(NULL) { } - TaggedASTDecl(D *_decl) : decl(_decl) { } - bool IsValid() const { return (decl != NULL); } - bool IsInvalid() const { return !IsValid(); } - D *operator->() const { return decl; } - D *decl; -}; - -template class TD, class D1> -TD -DynCast(TD source) -{ - return TD (dyn_cast(source.decl)); -} - -template class DeclFromParser; -template class DeclFromUser; - -template class DeclFromParser : public TaggedASTDecl { -public: - DeclFromParser() : TaggedASTDecl() { } - DeclFromParser(D *_decl) : TaggedASTDecl(_decl) { } - - DeclFromUser GetOrigin(ClangASTImporter *importer); -}; - -template class DeclFromUser : public TaggedASTDecl { -public: - DeclFromUser() : TaggedASTDecl() { } - DeclFromUser(D *_decl) : TaggedASTDecl(_decl) { } - - DeclFromParser Import(ClangASTImporter *importer, ASTContext &dest_ctx); -}; - -template -DeclFromUser -DeclFromParser::GetOrigin(ClangASTImporter *importer) -{ - DeclFromUser <> origin_decl; - importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); - if (origin_decl.IsInvalid()) - return DeclFromUser(); - return DeclFromUser(dyn_cast(origin_decl.decl)); -} - -template -DeclFromParser -DeclFromUser::Import(ClangASTImporter *importer, ASTContext &dest_ctx) -{ - DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); - if (parser_generic_decl.IsInvalid()) - return DeclFromParser(); - return DeclFromParser(dyn_cast(parser_generic_decl.decl)); -} - -static bool -FindObjCMethodDeclsWithOrigin (unsigned int current_id, - NameSearchContext &context, - ObjCInterfaceDecl *original_interface_decl, - clang::ASTContext *ast_context, - ClangASTImporter *ast_importer, - const char *log_info) -{ - const DeclarationName &decl_name(context.m_decl_name); - clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); - - Selector original_selector; - - if (decl_name.isObjCZeroArgSelector()) - { - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); - original_selector = original_ctx->Selectors.getSelector(0, &ident); - } - else if (decl_name.isObjCOneArgSelector()) - { - const std::string &decl_name_string = decl_name.getAsString(); - std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); - IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); - original_selector = original_ctx->Selectors.getSelector(1, &ident); - } - else - { - SmallVector idents; - - clang::Selector sel = decl_name.getObjCSelector(); - - unsigned num_args = sel.getNumArgs(); - - for (unsigned i = 0; - i != num_args; - ++i) - { - idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); - } - - original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); - } - - DeclarationName original_decl_name(original_selector); - - llvm::SmallVector methods; - - ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); - - if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) - { - methods.push_back(instance_method_decl); - } - else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) - { - methods.push_back(class_method_decl); - } - - if (methods.empty()) - { - return false; - } - - for (NamedDecl *named_decl : methods) - { - if (!named_decl) - continue; - - ObjCMethodDecl *result_method = dyn_cast(named_decl); - - if (!result_method) - continue; - - Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); - - if (!copied_decl) - continue; - - ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); - - if (!copied_method_decl) - continue; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); - } - - context.AddNamedDecl(copied_method_decl); - } - - return true; -} - -void -ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - const DeclarationName &decl_name(context.m_decl_name); - const DeclContext *decl_ctx(context.m_decl_context); - - const ObjCInterfaceDecl *interface_decl = dyn_cast(decl_ctx); - - if (!interface_decl) - return; - - do - { - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; - - m_ast_importer->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); - - if (!original_decl) - break; - - ObjCInterfaceDecl *original_interface_decl = dyn_cast(original_decl); - - if (FindObjCMethodDeclsWithOrigin(current_id, - context, - original_interface_decl, - m_ast_context, - m_ast_importer, - "at origin")) - return; // found it, no need to look any further - } while (0); - - StreamString ss; - - if (decl_name.isObjCZeroArgSelector()) - { - ss.Printf("%s", decl_name.getAsString().c_str()); - } - else if (decl_name.isObjCOneArgSelector()) - { - ss.Printf("%s", decl_name.getAsString().c_str()); - } - else - { - clang::Selector sel = decl_name.getObjCSelector(); - - for (unsigned i = 0, e = sel.getNumArgs(); - i != e; - ++i) - { - llvm::StringRef r = sel.getNameForSlot(i); - ss.Printf("%s:", r.str().c_str()); - } - } - ss.Flush(); - - if (strstr(ss.GetData(), "$__lldb")) - return; // we don't need any results - - ConstString selector_name(ss.GetData()); - - if (log) - log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]", - current_id, static_cast(m_ast_context), - interface_decl->getNameAsString().c_str(), - selector_name.AsCString()); - SymbolContextList sc_list; - - const bool include_symbols = false; - const bool include_inlines = false; - const bool append = false; - - std::string interface_name = interface_decl->getNameAsString(); - - do - { - StreamString ms; - ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); - ms.Flush(); - ConstString instance_method_name(ms.GetData()); - - m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); - - if (sc_list.GetSize()) - break; - - ms.Clear(); - ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); - ms.Flush(); - ConstString class_method_name(ms.GetData()); - - m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); - - if (sc_list.GetSize()) - break; - - // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in - // categories on the desired class. - - SymbolContextList candidate_sc_list; - - m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list); - - for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); - ci != ce; - ++ci) - { - SymbolContext candidate_sc; - - if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) - continue; - - if (!candidate_sc.function) - continue; - - const char *candidate_name = candidate_sc.function->GetName().AsCString(); - - const char *cursor = candidate_name; - - if (*cursor != '+' && *cursor != '-') - continue; - - ++cursor; - - if (*cursor != '[') - continue; - - ++cursor; - - size_t interface_len = interface_name.length(); - - if (strncmp(cursor, interface_name.c_str(), interface_len)) - continue; - - cursor += interface_len; - - if (*cursor == ' ' || *cursor == '(') - sc_list.Append(candidate_sc); - } - } - while (0); - - if (sc_list.GetSize()) - { - // We found a good function symbol. Use that. - - for (uint32_t i = 0, e = sc_list.GetSize(); - i != e; - ++i) - { - SymbolContext sc; - - if (!sc_list.GetContextAtIndex(i, sc)) - continue; - - if (!sc.function) - continue; - - DeclContext *function_ctx = sc.function->GetClangDeclContext(); - - if (!function_ctx) - continue; - - ObjCMethodDecl *method_decl = dyn_cast(function_ctx); - - if (!method_decl) - continue; - - ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); - - if (!found_interface_decl) - continue; - - if (found_interface_decl->getName() == interface_decl->getName()) - { - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); - - if (!copied_decl) - continue; - - ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); - - if (!copied_method_decl) - continue; - - if (log) - { - ASTDumper dumper((Decl*)copied_method_decl); - log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); - } - - context.AddNamedDecl(copied_method_decl); - } - } - - return; - } - - // Try the debug information. - - do - { - ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(interface_decl)); - - if (!complete_interface_decl) - break; - - // We found the complete interface. The runtime never needs to be queried in this scenario. - - DeclFromUser complete_iface_decl(complete_interface_decl); - - if (complete_interface_decl == interface_decl) - break; // already checked this one - - if (log) - log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, static_cast(complete_interface_decl), - static_cast(&complete_iface_decl->getASTContext())); - - FindObjCMethodDeclsWithOrigin(current_id, - context, - complete_interface_decl, - m_ast_context, - m_ast_importer, - "in debug info"); - - return; - } - while (0); - - do - { - // Check the modules only if the debug information didn't have a complete interface. - - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - ConstString interface_name(interface_decl->getNameAsString().c_str()); - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!modules_decl_vendor->FindDecls(interface_name, - append, - max_matches, - decls)) - break; - - ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast(decls[0]); - - if (!interface_decl_from_modules) - break; - - if (FindObjCMethodDeclsWithOrigin(current_id, - context, - interface_decl_from_modules, - m_ast_context, - m_ast_importer, - "in modules")) - return; - } - } - while (0); - - do - { - // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. - - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - break; - - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - - if (!language_runtime) - break; - - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - - if (!decl_vendor) - break; - - ConstString interface_name(interface_decl->getNameAsString().c_str()); - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!decl_vendor->FindDecls(interface_name, - append, - max_matches, - decls)) - break; - - ObjCInterfaceDecl *runtime_interface_decl = dyn_cast(decls[0]); - - if (!runtime_interface_decl) - break; - - FindObjCMethodDeclsWithOrigin(current_id, - context, - runtime_interface_decl, - m_ast_context, - m_ast_importer, - "in runtime"); - } - while(0); -} - -static bool -FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, - NameSearchContext &context, - clang::ASTContext &ast_context, - ClangASTImporter *ast_importer, - DeclFromUser &origin_iface_decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (origin_iface_decl.IsInvalid()) - return false; - - std::string name_str = context.m_decl_name.getAsString(); - StringRef name(name_str.c_str()); - IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); - - DeclFromUser origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); - - bool found = false; - - if (origin_property_decl.IsValid()) - { - DeclFromParser parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); - if (parser_property_decl.IsValid()) - { - if (log) - { - ASTDumper dumper((Decl*)parser_property_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); - } - - context.AddNamedDecl(parser_property_decl.decl); - found = true; - } - } - - DeclFromUser origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); - - if (origin_ivar_decl.IsValid()) - { - DeclFromParser parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); - if (parser_ivar_decl.IsValid()) - { - if (log) - { - ASTDumper dumper((Decl*)parser_ivar_decl.decl); - log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); - } - - context.AddNamedDecl(parser_ivar_decl.decl); - found = true; - } - } - - return found; -} - -void -ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - DeclFromParser parser_iface_decl(cast(context.m_decl_context)); - DeclFromUser origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer)); - - ConstString class_name(parser_iface_decl->getNameAsString().c_str()); - - if (log) - log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", - current_id, static_cast(m_ast_context), - parser_iface_decl->getNameAsString().c_str(), - context.m_decl_name.getAsString().c_str()); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, - origin_iface_decl)) - return; - - if (log) - log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", - current_id, static_cast(origin_iface_decl.decl), - static_cast(&origin_iface_decl->getASTContext())); - - SymbolContext null_sc; - TypeList type_list; - - do - { - ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(parser_iface_decl.decl)); - - if (!complete_interface_decl) - break; - - // We found the complete interface. The runtime never needs to be queried in this scenario. - - DeclFromUser complete_iface_decl(complete_interface_decl); - - if (complete_iface_decl.decl == origin_iface_decl.decl) - break; // already checked this one - - if (log) - log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast(complete_iface_decl.decl), - static_cast(&complete_iface_decl->getASTContext())); - - FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, - complete_iface_decl); - - return; - } - while(0); - - do - { - // Check the modules only if the debug information didn't have a complete interface. - - ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); - - if (!modules_decl_vendor) - break; - - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!modules_decl_vendor->FindDecls(class_name, - append, - max_matches, - decls)) - break; - - DeclFromUser interface_decl_from_modules(dyn_cast(decls[0])); - - if (!interface_decl_from_modules.IsValid()) - break; - - if (log) - log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast(interface_decl_from_modules.decl), - static_cast(&interface_decl_from_modules->getASTContext())); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, - interface_decl_from_modules)) - return; - } - while(0); - - do - { - // Check the runtime only if the debug information didn't have a complete interface - // and nothing was in the modules. - - lldb::ProcessSP process(m_target->GetProcessSP()); - - if (!process) - return; - - ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); - - if (!language_runtime) - return; - - DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); - - if (!decl_vendor) - break; - - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!decl_vendor->FindDecls(class_name, - append, - max_matches, - decls)) - break; - - DeclFromUser interface_decl_from_runtime(dyn_cast(decls[0])); - - if (!interface_decl_from_runtime.IsValid()) - break; - - if (log) - log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", - current_id, - static_cast(interface_decl_from_runtime.decl), - static_cast(&interface_decl_from_runtime->getASTContext())); - - if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, - context, - *m_ast_context, - m_ast_importer, - interface_decl_from_runtime)) - return; - } - while(0); -} - -typedef llvm::DenseMap FieldOffsetMap; -typedef llvm::DenseMap BaseOffsetMap; - -template -static bool -ImportOffsetMap(llvm::DenseMap &destination_map, llvm::DenseMap &source_map, - ClangASTImporter *importer, ASTContext &dest_ctx) -{ - // When importing fields into a new record, clang has a hard requirement that - // fields be imported in field offset order. Since they are stored in a DenseMap - // with a pointer as the key type, this means we cannot simply iterate over the - // map, as the order will be non-deterministic. Instead we have to sort by the offset - // and then insert in sorted order. - typedef llvm::DenseMap MapType; - typedef typename MapType::value_type PairType; - std::vector 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; - }); - - for (const auto &item : sorted_items) - { - DeclFromUser user_decl(const_cast(item.first)); - DeclFromParser parser_decl(user_decl.Import(importer, dest_ctx)); - if (parser_decl.IsInvalid()) - return false; - destination_map.insert(std::pair(parser_decl.decl, item.second)); - } - - return true; -} - -template -bool -ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser &record, - BaseOffsetMap &base_offsets) -{ - for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), - be = (IsVirtual ? record->vbases_end() : record->bases_end()); - bi != be; ++bi) - { - if (!IsVirtual && bi->isVirtual()) - continue; - - const clang::Type *origin_base_type = bi->getType().getTypePtr(); - const clang::RecordType *origin_base_record_type = origin_base_type->getAs(); - - if (!origin_base_record_type) - return false; - - DeclFromUser origin_base_record(origin_base_record_type->getDecl()); - - if (origin_base_record.IsInvalid()) - return false; - - DeclFromUser origin_base_cxx_record(DynCast(origin_base_record)); - - if (origin_base_cxx_record.IsInvalid()) - return false; - - CharUnits base_offset; - - if (IsVirtual) - base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); - else - base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); - - base_offsets.insert(std::pair(origin_base_cxx_record.decl, base_offset)); - } - - return true; -} - -bool -ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, - FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, - BaseOffsetMap &virtual_base_offsets) -{ - ClangASTMetrics::RegisterRecordLayout(); - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']", - current_id, static_cast(m_ast_context), - static_cast(record), - record->getNameAsString().c_str()); - - DeclFromParser parser_record(record); - DeclFromUser origin_record(parser_record.GetOrigin(m_ast_importer)); - - if (origin_record.IsInvalid()) - return false; - - FieldOffsetMap origin_field_offsets; - BaseOffsetMap origin_base_offsets; - BaseOffsetMap origin_virtual_base_offsets; - - ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast(origin_record.decl)); - - if (!origin_record.decl->getDefinition()) - return false; - - const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); - - int field_idx = 0, field_count = record_layout.getFieldCount(); - - for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) - { - if (field_idx >= field_count) - return false; // Layout didn't go well. Bail out. - - uint64_t field_offset = record_layout.getFieldOffset(field_idx); - - origin_field_offsets.insert(std::pair(*fi, field_offset)); - - field_idx++; - } - - ASTContext &parser_ast_context(record->getASTContext()); - - DeclFromUser origin_cxx_record(DynCast(origin_record)); - - if (origin_cxx_record.IsValid()) - { - if (!ExtractBaseOffsets(record_layout, origin_cxx_record, origin_base_offsets) || - !ExtractBaseOffsets(record_layout, origin_cxx_record, origin_virtual_base_offsets)) - return false; - } - - if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer, parser_ast_context) || - !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer, parser_ast_context) || - !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer, parser_ast_context)) - return false; - - size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); - alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); - - if (log) - { - log->Printf("LRT[%u] returned:", current_id); - log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, - static_cast(origin_record.decl)); - log->Printf("LRT[%u] Size = %" PRId64, current_id, size); - log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); - log->Printf("LRT[%u] Fields:", current_id); - for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); - fi != fe; - ++fi) - { - log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, - static_cast(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); - } - DeclFromParser parser_cxx_record = DynCast(parser_record); - if (parser_cxx_record.IsValid()) - { - log->Printf("LRT[%u] Bases:", current_id); - for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); - bi != be; - ++bi) - { - bool is_virtual = bi->isVirtual(); - - QualType base_type = bi->getType(); - const RecordType *base_record_type = base_type->getAs(); - DeclFromParser base_record(base_record_type->getDecl()); - DeclFromParser base_cxx_record = DynCast(base_record); - - log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, - (is_virtual ? "Virtual " : ""), static_cast(base_cxx_record.decl), - base_cxx_record.decl->getNameAsString().c_str(), - (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() - : base_offsets[base_cxx_record.decl].getQuantity())); - } - } - else - { - log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); - } - } - - return true; -} - -void -ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, - const ConstString &name, - ClangASTImporter::NamespaceMapSP &parent_map) const -{ - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - { - if (parent_map && parent_map->size()) - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s", - current_id, static_cast(m_ast_context), - name.GetCString(), - parent_map->begin()->second.GetNamespaceDecl()->getDeclName().getAsString().c_str()); - else - log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s", - current_id, static_cast(m_ast_context), - name.GetCString()); - } - - if (parent_map) - { - for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end(); - i != e; - ++i) - { - ClangNamespaceDecl found_namespace_decl; - - lldb::ModuleSP module_sp = i->first; - ClangNamespaceDecl module_parent_namespace_decl = i->second; - - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - - if (!symbol_vendor) - continue; - - SymbolContext null_sc; - - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl); - - if (!found_namespace_decl) - continue; - - namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); - - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - module_sp->GetFileSpec().GetFilename().GetCString()); - } - } - else - { - const ModuleList &target_images = m_target->GetImages(); - Mutex::Locker modules_locker(target_images.GetMutex()); - - ClangNamespaceDecl null_namespace_decl; - - for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) - { - lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); - - if (!image) - continue; - - ClangNamespaceDecl found_namespace_decl; - - SymbolVendor *symbol_vendor = image->GetSymbolVendor(); - - if (!symbol_vendor) - continue; - - SymbolContext null_sc; - - found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); - - if (!found_namespace_decl) - continue; - - namespace_map->push_back(std::pair(image, found_namespace_decl)); - - if (log) - log->Printf(" CMN[%u] Found namespace %s in module %s", - current_id, - name.GetCString(), - image->GetFileSpec().GetFilename().GetCString()); - } - } -} - -NamespaceDecl * -ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) -{ - if (!namespace_decls) - return NULL; - - const ClangNamespaceDecl &namespace_decl = namespace_decls->begin()->second; - - Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, namespace_decl.GetASTContext(), namespace_decl.GetNamespaceDecl()); - - if (!copied_decl) - return NULL; - - NamespaceDecl *copied_namespace_decl = dyn_cast(copied_decl); - - if (!copied_namespace_decl) - return NULL; - - context.m_decls.push_back(copied_namespace_decl); - - m_ast_importer->RegisterNamespaceMap(copied_namespace_decl, namespace_decls); - - return dyn_cast(copied_decl); -} - -ClangASTType -ClangASTSource::GuardedCopyType (const ClangASTType &src_type) -{ - ClangASTMetrics::RegisterLLDBImport(); - - SetImportInProgress(true); - - QualType copied_qual_type = m_ast_importer->CopyType (m_ast_context, src_type.GetASTContext(), src_type.GetQualType()); - - SetImportInProgress(false); - - if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) - // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types - // on occasion. - return ClangASTType(); - - return ClangASTType(m_ast_context, copied_qual_type); -} - -clang::NamedDecl * -NameSearchContext::AddVarDecl(const ClangASTType &type) -{ - assert (type && "Type for variable must be valid!"); - - if (!type.IsValid()) - return NULL; - - IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); - - clang::ASTContext *ast = type.GetASTContext(); - - clang::NamedDecl *Decl = VarDecl::Create(*ast, - const_cast(m_decl_context), - SourceLocation(), - SourceLocation(), - ii, - type.GetQualType(), - 0, - SC_Static); - m_decls.push_back(Decl); - - return Decl; -} - -clang::NamedDecl * -NameSearchContext::AddFunDecl (const ClangASTType &type, bool extern_c) -{ - assert (type && "Type for variable must be valid!"); - - if (!type.IsValid()) - return NULL; - - if (m_function_types.count(type)) - return NULL; - - m_function_types.insert(type); - - QualType qual_type (type.GetQualType()); - - clang::ASTContext *ast = type.GetASTContext(); - - const bool isInlineSpecified = false; - const bool hasWrittenPrototype = true; - const bool isConstexprSpecified = false; - - clang::DeclContext *context = const_cast(m_decl_context); - - if (extern_c) { - context = LinkageSpecDecl::Create(*ast, - context, - SourceLocation(), - SourceLocation(), - clang::LinkageSpecDecl::LanguageIDs::lang_c, - false); - } - - clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, - context, - SourceLocation(), - SourceLocation(), - m_decl_name.getAsIdentifierInfo(), - qual_type, - NULL, - SC_Extern, - isInlineSpecified, - hasWrittenPrototype, - isConstexprSpecified); - - // We have to do more than just synthesize the FunctionDecl. We have to - // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do - // this, we raid the function's FunctionProtoType for types. - - const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs(); - - if (func_proto_type) - { - unsigned NumArgs = func_proto_type->getNumParams(); - unsigned ArgIndex; - - SmallVector parm_var_decls; - - for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) - { - QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); - - parm_var_decls.push_back(ParmVarDecl::Create (*ast, - const_cast(context), - SourceLocation(), - SourceLocation(), - NULL, - arg_qual_type, - NULL, - SC_Static, - NULL)); - } - - func_decl->setParams(ArrayRef(parm_var_decls)); - } - else - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("Function type wasn't a FunctionProtoType"); - } - - m_decls.push_back(func_decl); - - return func_decl; -} - -clang::NamedDecl * -NameSearchContext::AddGenericFunDecl() -{ - FunctionProtoType::ExtProtoInfo proto_info; - - proto_info.Variadic = true; - - QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result - ArrayRef(), // argument types - proto_info)); - - return AddFunDecl(ClangASTType (m_ast_source.m_ast_context, generic_function_type), true); -} - -clang::NamedDecl * -NameSearchContext::AddTypeDecl(const ClangASTType &clang_type) -{ - if (clang_type) - { - QualType qual_type = clang_type.GetQualType(); - - if (const TypedefType *typedef_type = llvm::dyn_cast(qual_type)) - { - TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); - - m_decls.push_back(typedef_name_decl); - - return (NamedDecl*)typedef_name_decl; - } - else if (const TagType *tag_type = qual_type->getAs()) - { - TagDecl *tag_decl = tag_type->getDecl(); - - m_decls.push_back(tag_decl); - - return tag_decl; - } - else if (const ObjCObjectType *objc_object_type = qual_type->getAs()) - { - ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); - - m_decls.push_back((NamedDecl*)interface_decl); - - return (NamedDecl*)interface_decl; - } - } - return NULL; -} - -void -NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) -{ - for (clang::NamedDecl *decl : result) - m_decls.push_back (decl); -} - -void -NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) -{ - m_decls.push_back (decl); -} diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp deleted file mode 100644 index 2c66a0aa4278..000000000000 --- a/source/Expression/ClangExpressionDeclMap.cpp +++ /dev/null @@ -1,2171 +0,0 @@ -//===-- ClangExpressionDeclMap.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/Expression/ClangExpressionDeclMap.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/Decl.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/Address.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/RegisterValue.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ASTDumper.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/Materializer.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangNamespaceDecl.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Symbol/Type.h" -#include "lldb/Symbol/TypeList.h" -#include "lldb/Symbol/Variable.h" -#include "lldb/Symbol/VariableList.h" -#include "lldb/Target/CPPLanguageRuntime.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" - -using namespace lldb; -using namespace lldb_private; -using namespace clang; - -ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, ExecutionContext &exe_ctx) : - ClangASTSource (exe_ctx.GetTargetSP()), - m_found_entities (), - m_struct_members (), - m_keep_result_in_memory (keep_result_in_memory), - m_parser_vars (), - m_struct_vars () -{ - EnableStructVars(); -} - -ClangExpressionDeclMap::~ClangExpressionDeclMap() -{ - // Note: The model is now that the parser's AST context and all associated - // data does not vanish until the expression has been executed. This means - // that valuable lookup data (like namespaces) doesn't vanish, but - - DidParse(); - DisableStructVars(); -} - -bool -ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, - Materializer *materializer) -{ - ClangASTMetrics::ClearLocalCounters(); - - EnableParserVars(); - m_parser_vars->m_exe_ctx = exe_ctx; - - Target *target = exe_ctx.GetTargetPtr(); - if (exe_ctx.GetFramePtr()) - m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); - else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) - m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); - else if (exe_ctx.GetProcessPtr()) - { - m_parser_vars->m_sym_ctx.Clear(true); - m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); - } - else if (target) - { - m_parser_vars->m_sym_ctx.Clear(true); - m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); - } - - if (target) - { - m_parser_vars->m_persistent_vars = &target->GetPersistentVariables(); - - if (!target->GetScratchClangASTContext()) - return false; - } - - m_parser_vars->m_target_info = GetTargetInfo(); - m_parser_vars->m_materializer = materializer; - - return true; -} - -void -ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen) -{ - assert(m_parser_vars); - m_parser_vars->m_code_gen = code_gen; -} - -void -ClangExpressionDeclMap::DidParse() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - ClangASTMetrics::DumpCounters(log); - - if (m_parser_vars.get()) - { - for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); - entity_index < num_entities; - ++entity_index) - { - ClangExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index)); - if (var_sp) - var_sp->DisableParserVars(GetParserID()); - } - - for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize(); - pvar_index < num_pvars; - ++pvar_index) - { - ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); - if (pvar_sp) - pvar_sp->DisableParserVars(GetParserID()); - } - - DisableParserVars(); - } -} - -// Interface for IRForTarget - -ClangExpressionDeclMap::TargetInfo -ClangExpressionDeclMap::GetTargetInfo() -{ - assert (m_parser_vars.get()); - - TargetInfo ret; - - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - ret.byte_order = process->GetByteOrder(); - ret.address_byte_size = process->GetAddressByteSize(); - } - else - { - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - ret.byte_order = target->GetArchitecture().GetByteOrder(); - ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); - } - } - - return ret; -} - -bool -ClangExpressionDeclMap::AddPersistentVariable -( - const NamedDecl *decl, - const ConstString &name, - TypeFromParser parser_type, - bool is_result, - bool is_lvalue -) -{ - assert (m_parser_vars.get()); - - if (m_parser_vars->m_materializer && is_result) - { - Error err; - - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Target *target = exe_ctx.GetTargetPtr(); - if (target == NULL) - return false; - - ASTContext *context(target->GetScratchClangASTContext()->getASTContext()); - - TypeFromUser user_type(m_ast_importer->DeportType(context, - parser_type.GetASTContext(), - parser_type.GetOpaqueQualType()), - context); - - uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, is_lvalue, m_keep_result_in_memory, err); - - ClangExpressionVariableSP var_sp = m_found_entities.CreateVariable(exe_ctx.GetBestExecutionContextScope(), - name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size); - - if (!var_sp) - return false; - - var_sp->EnableParserVars(GetParserID()); - - ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID()); - - parser_vars->m_named_decl = decl; - parser_vars->m_parser_type = parser_type; - - var_sp->EnableJITVars(GetParserID()); - - ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()); - - jit_vars->m_offset = offset; - - return true; - } - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Target *target = exe_ctx.GetTargetPtr(); - if (target == NULL) - return false; - - ASTContext *context(target->GetScratchClangASTContext()->getASTContext()); - - TypeFromUser user_type(m_ast_importer->DeportType(context, - parser_type.GetASTContext(), - parser_type.GetOpaqueQualType()), - context); - - if (!user_type.GetOpaqueQualType()) - { - if (log) - log->Printf("Persistent variable's type wasn't copied successfully"); - return false; - } - - if (!m_parser_vars->m_target_info.IsValid()) - return false; - - ClangExpressionVariableSP var_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (), - name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size); - - if (!var_sp) - return false; - - var_sp->m_frozen_sp->SetHasCompleteType(); - - if (is_result) - var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; - else - var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist - - if (is_lvalue) - { - var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference; - } - else - { - var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; - var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; - } - - if (m_keep_result_in_memory) - { - var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; - } - - if (log) - log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags); - - var_sp->EnableParserVars(GetParserID()); - - ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID()); - - parser_vars->m_named_decl = decl; - parser_vars->m_parser_type = parser_type; - - return true; -} - -bool -ClangExpressionDeclMap::AddValueToStruct -( - const NamedDecl *decl, - const ConstString &name, - llvm::Value *value, - size_t size, - lldb::offset_t alignment -) -{ - assert (m_struct_vars.get()); - assert (m_parser_vars.get()); - - bool is_persistent_variable = false; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_struct_vars->m_struct_laid_out = false; - - if (m_struct_members.GetVariable(decl, GetParserID())) - return true; - - ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl, GetParserID())); - - if (!var_sp) - { - var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl, GetParserID()); - is_persistent_variable = true; - } - - if (!var_sp) - return false; - - if (log) - log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", - static_cast(decl), name.GetCString(), - var_sp->GetName().GetCString()); - - // We know entity->m_parser_vars is valid because we used a parser variable - // to find it - - ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(GetParserID()); - - parser_vars->m_llvm_value = value; - - if (ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID())) - { - // We already laid this out; do not touch - - if (log) - log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset); - } - - var_sp->EnableJITVars(GetParserID()); - - ClangExpressionVariable::JITVars *jit_vars = var_sp->GetJITVars(GetParserID()); - - jit_vars->m_alignment = alignment; - jit_vars->m_size = size; - - m_struct_members.AddVariable(var_sp); - - if (m_parser_vars->m_materializer) - { - uint32_t offset = 0; - - Error err; - - if (is_persistent_variable) - { - offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, err); - } - else - { - if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) - offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); - else if (const RegisterInfo *reg_info = var_sp->GetRegisterInfo()) - offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); - else if (parser_vars->m_lldb_var) - offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err); - } - - if (!err.Success()) - return false; - - if (log) - log->Printf("Placed at 0x%llx", (unsigned long long)offset); - - jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. - } - - return true; -} - -bool -ClangExpressionDeclMap::DoStructLayout () -{ - assert (m_struct_vars.get()); - - if (m_struct_vars->m_struct_laid_out) - return true; - - if (!m_parser_vars->m_materializer) - return false; - - m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment(); - m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize(); - m_struct_vars->m_struct_laid_out = true; - return true; -} - -bool ClangExpressionDeclMap::GetStructInfo -( - uint32_t &num_elements, - size_t &size, - lldb::offset_t &alignment -) -{ - assert (m_struct_vars.get()); - - if (!m_struct_vars->m_struct_laid_out) - return false; - - num_elements = m_struct_members.GetSize(); - size = m_struct_vars->m_struct_size; - alignment = m_struct_vars->m_struct_alignment; - - return true; -} - -bool -ClangExpressionDeclMap::GetStructElement -( - const NamedDecl *&decl, - llvm::Value *&value, - lldb::offset_t &offset, - ConstString &name, - uint32_t index -) -{ - assert (m_struct_vars.get()); - - if (!m_struct_vars->m_struct_laid_out) - return false; - - if (index >= m_struct_members.GetSize()) - return false; - - ClangExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); - - if (!member_sp) - return false; - - ClangExpressionVariable::ParserVars *parser_vars = member_sp->GetParserVars(GetParserID()); - ClangExpressionVariable::JITVars *jit_vars = member_sp->GetJITVars(GetParserID()); - - if (!parser_vars || - !jit_vars || - !member_sp->GetValueObject()) - return false; - - decl = parser_vars->m_named_decl; - value = parser_vars->m_llvm_value; - offset = jit_vars->m_offset; - name = member_sp->GetName(); - - return true; -} - -bool -ClangExpressionDeclMap::GetFunctionInfo -( - const NamedDecl *decl, - uint64_t &ptr -) -{ - ClangExpressionVariableSP entity_sp(m_found_entities.GetVariable(decl, GetParserID())); - - if (!entity_sp) - return false; - - // We know m_parser_vars is valid since we searched for the variable by - // its NamedDecl - - ClangExpressionVariable::ParserVars *parser_vars = entity_sp->GetParserVars(GetParserID()); - - ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); - - return true; -} - -static void -FindCodeSymbolInContext -( - const ConstString &name, - SymbolContext &sym_ctx, - SymbolContextList &sc_list -) -{ - sc_list.Clear(); - SymbolContextList temp_sc_list; - if (sym_ctx.module_sp) - sym_ctx.module_sp->FindFunctions(name, - NULL, - eFunctionNameTypeAuto, - true, // include_symbols - false, // include_inlines - true, // append - temp_sc_list); - if (temp_sc_list.GetSize() == 0) - { - if (sym_ctx.target_sp) - sym_ctx.target_sp->GetImages().FindFunctions(name, - eFunctionNameTypeAuto, - true, // include_symbols - false, // include_inlines - true, // append - temp_sc_list); - } - - SymbolContextList internal_symbol_sc_list; - unsigned temp_sc_list_size = temp_sc_list.GetSize(); - for (unsigned i = 0; i < temp_sc_list_size; i++) - { - SymbolContext sc; - temp_sc_list.GetContextAtIndex(i, sc); - if (sc.function) - { - sc_list.Append(sc); - } - else if (sc.symbol) - { - if (sc.symbol->IsExternal()) - { - sc_list.Append(sc); - } - else - { - internal_symbol_sc_list.Append(sc); - } - } - } - - // If we had internal symbols and we didn't find any external symbols or - // functions in debug info, then fallback to the internal symbols - if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize()) - { - sc_list = internal_symbol_sc_list; - } -} - -bool -ClangExpressionDeclMap::GetFunctionAddress -( - const ConstString &name, - uint64_t &func_addr -) -{ - assert (m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; - Target *target = exe_ctx.GetTargetPtr(); - // Back out in all cases where we're not fully initialized - if (target == NULL) - return false; - if (!m_parser_vars->m_sym_ctx.target_sp) - return false; - - SymbolContextList sc_list; - - FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list); - - uint32_t sc_list_size = sc_list.GetSize(); - - if (sc_list_size == 0) - { - // We occasionally get debug information in which a const function is reported - // as non-const, so the mangled name is wrong. This is a hack to compensate. - - if (!strncmp(name.GetCString(), "_ZN", 3) && - strncmp(name.GetCString(), "_ZNK", 4)) - { - std::string fixed_scratch("_ZNK"); - fixed_scratch.append(name.GetCString() + 3); - ConstString fixed_name(fixed_scratch.c_str()); - - if (log) - log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString()); - - FindCodeSymbolInContext(fixed_name, m_parser_vars->m_sym_ctx, sc_list); - sc_list_size = sc_list.GetSize(); - } - } - - lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS; - - for (uint32_t i=0; iGetAddressRange().GetBaseAddress(); - if (func_so_addr.IsValid()) - { - callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false); - } - } - else if (sym_ctx.symbol) - { - if (sym_ctx.symbol->IsExternal()) - callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); - else - { - if (intern_callable_load_addr == LLDB_INVALID_ADDRESS) - intern_callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); - } - } - - if (callable_load_addr != LLDB_INVALID_ADDRESS) - { - func_addr = callable_load_addr; - return true; - } - } - - // See if we found an internal symbol - if (intern_callable_load_addr != LLDB_INVALID_ADDRESS) - { - func_addr = intern_callable_load_addr; - return true; - } - - return false; -} - -addr_t -ClangExpressionDeclMap::GetSymbolAddress (Target &target, - Process *process, - const ConstString &name, - lldb::SymbolType symbol_type, - lldb_private::Module *module) -{ - SymbolContextList sc_list; - - if (module) - module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); - else - target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); - - const uint32_t num_matches = sc_list.GetSize(); - addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; - - for (uint32_t i=0; iGetAddress(); - - if (!sym_address.IsValid()) - continue; - - switch (sym_ctx.symbol->GetType()) - { - case eSymbolTypeCode: - case eSymbolTypeTrampoline: - symbol_load_addr = sym_address.GetCallableLoadAddress (&target); - break; - - case eSymbolTypeResolver: - symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); - break; - - case eSymbolTypeReExported: - { - ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); - if (reexport_name) - { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); - if (reexport_module_spec.GetPlatformFileSpec()) - { - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - if (!reexport_module_sp) - { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - } - } - symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); - } - } - break; - - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeInvalid: - case eSymbolTypeAbsolute: - case eSymbolTypeException: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeUndefined: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - symbol_load_addr = sym_address.GetLoadAddress (&target); - break; - } - } - - if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) - { - ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); - - if (runtime) - { - symbol_load_addr = runtime->LookupRuntimeSymbol(name); - } - } - - return symbol_load_addr; -} - -addr_t -ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type) -{ - assert (m_parser_vars.get()); - - if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) - return false; - - return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type); -} - -const Symbol * -ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, - const ConstString &name, - lldb_private::Module *module) -{ - SymbolContextList sc_list; - - if (module) - module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); - else - target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); - - const uint32_t matches = sc_list.GetSize(); - for (uint32_t i=0; iGetAddress(); - - if (sym_address.IsValid()) - { - switch (symbol->GetType()) - { - case eSymbolTypeData: - case eSymbolTypeRuntime: - case eSymbolTypeAbsolute: - case eSymbolTypeObjCClass: - case eSymbolTypeObjCMetaClass: - case eSymbolTypeObjCIVar: - if (symbol->GetDemangledNameIsSynthesized()) - { - // If the demangled name was synthesized, then don't use it - // for expressions. Only let the symbol match if the mangled - // named matches for these symbols. - if (symbol->GetMangled().GetMangledName() != name) - break; - } - return symbol; - - case eSymbolTypeReExported: - { - ConstString reexport_name = symbol->GetReExportedSymbolName(); - if (reexport_name) - { - ModuleSP reexport_module_sp; - ModuleSpec reexport_module_spec; - reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary(); - if (reexport_module_spec.GetPlatformFileSpec()) - { - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - if (!reexport_module_sp) - { - reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); - reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); - } - } - // Don't allow us to try and resolve a re-exported symbol if it is the same - // as the current symbol - if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get()) - return NULL; - - return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get()); - } - } - break; - - case eSymbolTypeCode: // We already lookup functions elsewhere - case eSymbolTypeVariable: - case eSymbolTypeLocal: - case eSymbolTypeParam: - case eSymbolTypeTrampoline: - case eSymbolTypeInvalid: - case eSymbolTypeException: - case eSymbolTypeSourceFile: - case eSymbolTypeHeaderFile: - case eSymbolTypeObjectFile: - case eSymbolTypeCommonBlock: - case eSymbolTypeBlock: - case eSymbolTypeVariableType: - case eSymbolTypeLineEntry: - case eSymbolTypeLineHeader: - case eSymbolTypeScopeBegin: - case eSymbolTypeScopeEnd: - case eSymbolTypeAdditional: - case eSymbolTypeCompiler: - case eSymbolTypeInstrumentation: - case eSymbolTypeUndefined: - case eSymbolTypeResolver: - break; - } - } - } - } - - return NULL; -} - -lldb::VariableSP -ClangExpressionDeclMap::FindGlobalVariable -( - Target &target, - ModuleSP &module, - const ConstString &name, - ClangNamespaceDecl *namespace_decl, - TypeFromUser *type -) -{ - VariableList vars; - - if (module && namespace_decl) - module->FindGlobalVariables (name, namespace_decl, true, -1, vars); - else - target.GetImages().FindGlobalVariables(name, true, -1, vars); - - if (vars.GetSize()) - { - if (type) - { - for (size_t i = 0; i < vars.GetSize(); ++i) - { - VariableSP var_sp = vars.GetVariableAtIndex(i); - - if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetClangFullType())) - return var_sp; - } - } - else - { - return vars.GetVariableAtIndex(0); - } - } - - return VariableSP(); -} - -// Interface for ClangASTSource - -void -ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) -{ - assert (m_ast_context); - - ClangASTMetrics::RegisterVisibleQuery(); - - const ConstString name(context.m_decl_name.getAsString().c_str()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (GetImportInProgress()) - { - if (log && log->GetVerbose()) - log->Printf("Ignoring a query during an import"); - return; - } - - static unsigned int invocation_id = 0; - unsigned int current_id = invocation_id++; - - if (log) - { - if (!context.m_decl_context) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString()); - else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str()); - else - log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName()); - } - - if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) - { - ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer->GetNamespaceMap(namespace_context); - - if (log && log->GetVerbose()) - log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", - current_id, static_cast(namespace_map.get()), - (int)namespace_map->size()); - - if (!namespace_map) - return; - - for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); - i != e; - ++i) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s", - current_id, - i->second.GetNamespaceDecl()->getNameAsString().c_str(), - i->first->GetFileSpec().GetFilename().GetCString()); - - FindExternalVisibleDecls(context, - i->first, - i->second, - current_id); - } - } - else if (isa(context.m_decl_context)) - { - ClangNamespaceDecl namespace_decl; - - if (log) - log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id); - - FindExternalVisibleDecls(context, - lldb::ModuleSP(), - namespace_decl, - current_id); - } - - if (!context.m_found.variable) - ClangASTSource::FindExternalVisibleDecls(context); -} - -void -ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, - lldb::ModuleSP module_sp, - ClangNamespaceDecl &namespace_decl, - unsigned int current_id) -{ - assert (m_ast_context); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SymbolContextList sc_list; - - const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - if (name_unique_cstr == NULL) - return; - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) - return; - - // Only look for functions by name out in our symbols if the function - // doesn't start with our phony prefix of '$' - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); - if (name_unique_cstr[0] == '$' && !namespace_decl) - { - static ConstString g_lldb_class_name ("$__lldb_class"); - - if (name == g_lldb_class_name) - { - // Clang is looking for the type of "this" - - if (frame == NULL) - return; - - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction); - - if (!sym_ctx.function) - return; - - // Get the block that defines the function - Block *function_block = sym_ctx.GetFunctionBlock(); - - if (!function_block) - return; - - clang::DeclContext *decl_context = function_block->GetClangDeclContext(); - - if (!decl_context) - return; - - clang::CXXMethodDecl *method_decl = llvm::dyn_cast(decl_context); - - if (method_decl) - { - clang::CXXRecordDecl *class_decl = method_decl->getParent(); - - QualType class_qual_type(class_decl->getTypeForDecl(), 0); - - TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), - &class_decl->getASTContext()); - - if (log) - { - ASTDumper ast_dumper(class_qual_type); - log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); - } - - TypeFromParser class_type = CopyClassType(class_user_type, current_id); - - if (!class_type.IsValid()) - return; - - TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(class_type.GetOpaqueQualType())); - - if (!type_source_info) - return; - - TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context, - m_ast_context->getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - context.m_decl_name.getAsIdentifierInfo(), - type_source_info); - - - if (!typedef_decl) - return; - - context.AddNamedDecl(typedef_decl); - - if (method_decl->isInstance()) - { - // self is a pointer to the object - - QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); - - TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - &method_decl->getASTContext()); - - m_struct_vars->m_object_pointer_type = self_user_type; - } - } - else - { - // This branch will get hit if we are executing code in the context of a function that - // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a - // method of the class. In that case, just look up the "this" variable in the current - // scope and use its type. - // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer - // for C++ so it hasn't actually been tested. - - VariableList *vars = frame->GetVariableList(false); - - lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); - - if (this_var && - this_var->IsInScope(frame) && - this_var->LocationIsValidForFrame (frame)) - { - Type *this_type = this_var->GetType(); - - if (!this_type) - return; - - ClangASTType pointee_type = this_type->GetClangForwardType().GetPointeeType(); - - if (pointee_type.IsValid()) - { - if (log) - { - ASTDumper ast_dumper(this_type->GetClangFullType()); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); - } - - TypeFromUser class_user_type(pointee_type); - AddOneType(context, class_user_type, current_id); - - - TypeFromUser this_user_type(this_type->GetClangFullType()); - m_struct_vars->m_object_pointer_type = this_user_type; - return; - } - } - } - - return; - } - - static ConstString g_lldb_objc_class_name ("$__lldb_objc_class"); - if (name == g_lldb_objc_class_name) - { - // Clang is looking for the type of "*self" - - if (!frame) - return; - - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction); - - if (!sym_ctx.function) - return; - - // Get the block that defines the function - Block *function_block = sym_ctx.GetFunctionBlock(); - - if (!function_block) - return; - - clang::DeclContext *decl_context = function_block->GetClangDeclContext(); - - if (!decl_context) - return; - - clang::ObjCMethodDecl *method_decl = llvm::dyn_cast(decl_context); - - if (method_decl) - { - ObjCInterfaceDecl* self_interface = method_decl->getClassInterface(); - - if (!self_interface) - return; - - const clang::Type *interface_type = self_interface->getTypeForDecl(); - - if (!interface_type) - return; // This is unlikely, but we have seen crashes where this occurred - - TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), - &method_decl->getASTContext()); - - if (log) - { - ASTDumper ast_dumper(interface_type); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); - } - - AddOneType(context, class_user_type, current_id); - - if (method_decl->isInstanceMethod()) - { - // self is a pointer to the object - - QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); - - TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), - &method_decl->getASTContext()); - - m_struct_vars->m_object_pointer_type = self_user_type; - } - else - { - // self is a Class pointer - QualType class_type = method_decl->getASTContext().getObjCClassType(); - - TypeFromUser self_user_type(class_type.getAsOpaquePtr(), - &method_decl->getASTContext()); - - m_struct_vars->m_object_pointer_type = self_user_type; - } - - return; - } - else - { - // This branch will get hit if we are executing code in the context of a function that - // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a - // method of the class. In that case, just look up the "self" variable in the current - // scope and use its type. - - VariableList *vars = frame->GetVariableList(false); - - lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); - - if (self_var && - self_var->IsInScope(frame) && - self_var->LocationIsValidForFrame (frame)) - { - Type *self_type = self_var->GetType(); - - if (!self_type) - return; - - ClangASTType self_clang_type = self_type->GetClangFullType(); - - if (self_clang_type.IsObjCClassType()) - { - return; - } - else if (self_clang_type.IsObjCObjectPointerType()) - { - self_clang_type = self_clang_type.GetPointeeType(); - - if (!self_clang_type) - return; - - if (log) - { - ASTDumper ast_dumper(self_type->GetClangFullType()); - log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); - } - - TypeFromUser class_user_type (self_clang_type); - - AddOneType(context, class_user_type, current_id); - - TypeFromUser self_user_type(self_type->GetClangFullType()); - - m_struct_vars->m_object_pointer_type = self_user_type; - return; - } - } - } - - return; - } - - // any other $__lldb names should be weeded out now - if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) - return; - - do - { - if (!target) - break; - - ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext(); - - if (!scratch_clang_ast_context) - break; - - ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); - - if (!scratch_ast_context) - break; - - TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name); - - if (!ptype_type_decl) - break; - - Decl *parser_ptype_decl = m_ast_importer->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl); - - if (!parser_ptype_decl) - break; - - TypeDecl *parser_ptype_type_decl = dyn_cast(parser_ptype_decl); - - if (!parser_ptype_type_decl) - break; - - if (log) - log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString()); - - context.AddNamedDecl(parser_ptype_type_decl); - } while (0); - - ClangExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); - - if (pvar_sp) - { - AddOneVariable(context, pvar_sp, current_id); - return; - } - - const char *reg_name(&name.GetCString()[1]); - - if (m_parser_vars->m_exe_ctx.GetRegisterContext()) - { - const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name)); - - if (reg_info) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name); - - AddOneRegister(context, reg_info, current_id); - } - } - } - else - { - ValueObjectSP valobj; - VariableSP var; - Error err; - - if (frame && !namespace_decl) - { - valobj = frame->GetValueForVariableExpressionPath(name_unique_cstr, - eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsNoFragileObjcIvar | - StackFrame::eExpressionPathOptionsNoSyntheticChildren | - StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, - var, - err); - - // If we found a variable in scope, no need to pull up function names - if (err.Success() && var) - { - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - return; - } - } - - if (target) - { - var = FindGlobalVariable (*target, - module_sp, - name, - &namespace_decl, - NULL); - - if (var) - { - valobj = ValueObjectVariable::Create(target, var); - AddOneVariable(context, var, valobj, current_id); - context.m_found.variable = true; - return; - } - } - - std::vector decls_from_modules; - - if (target) - { - if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) - { - decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); - } - } - - if (!context.m_found.variable) - { - const bool include_inlines = false; - const bool append = false; - - if (namespace_decl && module_sp) - { - const bool include_symbols = false; - - module_sp->FindFunctions(name, - &namespace_decl, - eFunctionNameTypeBase, - include_symbols, - include_inlines, - append, - sc_list); - } - else if (target && !namespace_decl) - { - const bool include_symbols = true; - - // TODO Fix FindFunctions so that it doesn't return - // instance methods for eFunctionNameTypeBase. - - target->GetImages().FindFunctions(name, - eFunctionNameTypeFull, - include_symbols, - include_inlines, - append, - sc_list); - } - - if (sc_list.GetSize()) - { - Symbol *extern_symbol = NULL; - Symbol *non_extern_symbol = NULL; - - for (uint32_t index = 0, num_indices = sc_list.GetSize(); - index < num_indices; - ++index) - { - SymbolContext sym_ctx; - sc_list.GetContextAtIndex(index, sym_ctx); - - if (sym_ctx.function) - { - clang::DeclContext *decl_ctx = sym_ctx.function->GetClangDeclContext(); - - if (!decl_ctx) - continue; - - // Filter out class/instance methods. - if (dyn_cast(decl_ctx)) - continue; - if (dyn_cast(decl_ctx)) - continue; - - AddOneFunction(context, sym_ctx.function, NULL, current_id); - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } - else if (sym_ctx.symbol) - { - if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) - { - sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); - if (sym_ctx.symbol == NULL) - continue; - } - - if (sym_ctx.symbol->IsExternal()) - extern_symbol = sym_ctx.symbol; - else - non_extern_symbol = sym_ctx.symbol; - } - } - - if (!context.m_found.function_with_type_info) - { - for (clang::NamedDecl *decl : decls_from_modules) - { - if (llvm::isa(decl)) - { - clang::NamedDecl *copied_decl = llvm::cast(m_ast_importer->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); - context.AddNamedDecl(copied_decl); - context.m_found.function_with_type_info = true; - } - } - } - - if (!context.m_found.function_with_type_info) - { - if (extern_symbol) - { - AddOneFunction (context, NULL, extern_symbol, current_id); - context.m_found.function = true; - } - else if (non_extern_symbol) - { - AddOneFunction (context, NULL, non_extern_symbol, current_id); - context.m_found.function = true; - } - } - } - - if (!context.m_found.function_with_type_info) - { - // Try the modules next. - - do - { - if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) - { - bool append = false; - uint32_t max_matches = 1; - std::vector decls; - - if (!modules_decl_vendor->FindDecls(name, - append, - max_matches, - decls)) - break; - - clang::NamedDecl *const decl_from_modules = decls[0]; - - if (llvm::isa(decl_from_modules)) - { - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; - - if (!copied_function_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules", - current_id); - - break; - } - - if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) - { - DeclGroupRef decl_group_ref(copied_function_decl); - m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); - } - - context.AddNamedDecl(copied_function_decl); - - context.m_found.function_with_type_info = true; - context.m_found.function = true; - } - else if (llvm::isa(decl_from_modules)) - { - if (log) - { - log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", - current_id, - name.GetCString()); - } - - clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); - clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null(copied_decl) : nullptr; - - if (!copied_var_decl) - { - if (log) - log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", - current_id); - - break; - } - - context.AddNamedDecl(copied_var_decl); - - context.m_found.variable = true; - } - } - } while (0); - } - - if (target && !context.m_found.variable && !namespace_decl) - { - // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic - // data symbol, and -- if it is found -- treat it as a variable. - - const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); - - if (data_symbol) - { - std::string warning("got name from symbols: "); - warning.append(name.AsCString()); - const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); - m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); - AddOneGenericVariable(context, *data_symbol, current_id); - context.m_found.variable = true; - } - } - } - } -} - -//static clang_type_t -//MaybePromoteToBlockPointerType -//( -// ASTContext *ast_context, -// clang_type_t candidate_type -//) -//{ -// if (!candidate_type) -// return candidate_type; -// -// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); -// -// const PointerType *candidate_pointer_type = dyn_cast(candidate_qual_type); -// -// if (!candidate_pointer_type) -// return candidate_type; -// -// QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); -// -// const RecordType *pointee_record_type = dyn_cast(pointee_qual_type); -// -// if (!pointee_record_type) -// return candidate_type; -// -// RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); -// -// if (!pointee_record_decl->isRecord()) -// return candidate_type; -// -// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) -// return candidate_type; -// -// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); -// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type); -// -// return block_pointer_type.getAsOpaquePtr(); -//} - -bool -ClangExpressionDeclMap::GetVariableValue (VariableSP &var, - lldb_private::Value &var_location, - TypeFromUser *user_type, - TypeFromParser *parser_type) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Type *var_type = var->GetType(); - - if (!var_type) - { - if (log) - log->PutCString("Skipped a definition because it has no type"); - return false; - } - - ClangASTType var_clang_type = var_type->GetClangFullType(); - - if (!var_clang_type) - { - if (log) - log->PutCString("Skipped a definition because it has no Clang type"); - return false; - } - - ASTContext *ast = var_type->GetClangASTContext().getASTContext(); - - if (!ast) - { - if (log) - log->PutCString("There is no AST context for the current execution context"); - return false; - } - //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); - - DWARFExpression &var_location_expr = var->LocationExpression(); - - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - Error err; - - if (var->GetLocationIsConstantValueData()) - { - DataExtractor const_value_extractor; - - if (var_location_expr.GetExpressionData(const_value_extractor)) - { - var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); - var_location.SetValueType(Value::eValueTypeHostAddress); - } - else - { - if (log) - log->Printf("Error evaluating constant variable: %s", err.AsCString()); - return false; - } - } - - ClangASTType type_to_use = GuardedCopyType(var_clang_type); - - if (!type_to_use) - { - if (log) - log->Printf("Couldn't copy a variable's type into the parser's AST context"); - - return false; - } - - if (parser_type) - *parser_type = TypeFromParser(type_to_use); - - if (var_location.GetContextType() == Value::eContextTypeInvalid) - var_location.SetClangType(type_to_use); - - if (var_location.GetValueType() == Value::eValueTypeFileAddress) - { - SymbolContext var_sc; - var->CalculateSymbolContext(&var_sc); - - if (!var_sc.module_sp) - return false; - - Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList()); - - lldb::addr_t load_addr = so_addr.GetLoadAddress(target); - - if (load_addr != LLDB_INVALID_ADDRESS) - { - var_location.GetScalar() = load_addr; - var_location.SetValueType(Value::eValueTypeLoadAddress); - } - } - - if (user_type) - *user_type = TypeFromUser(var_clang_type); - - return true; -} - -void -ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id) -{ - assert (m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - TypeFromUser ut; - TypeFromParser pt; - Value var_location; - - if (!GetVariableValue (var, var_location, &ut, &pt)) - return; - - clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); - - if (parser_opaque_type.isNull()) - return; - - if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) - { - if (const TagType *tag_type = dyn_cast(parser_type)) - CompleteType(tag_type->getDecl()); - if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast(parser_type)) - CompleteType(objc_object_ptr_type->getInterfaceDecl()); - } - - - bool is_reference = pt.IsReferenceType(); - - NamedDecl *var_decl = NULL; - if (is_reference) - var_decl = context.AddVarDecl(pt); - else - var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); - - std::string decl_name(context.m_decl_name.getAsString()); - ConstString entity_name(decl_name.c_str()); - ClangExpressionVariableSP entity(m_found_entities.CreateVariable (valobj)); - - assert (entity.get()); - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - parser_vars->m_parser_type = pt; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value = var_location; - parser_vars->m_lldb_var = var; - - if (is_reference) - entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; - - if (log) - { - ASTDumper orig_dumper(ut.GetOpaqueQualType()); - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString()); - } -} - -void -ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, - ClangExpressionVariableSP &pvar_sp, - unsigned int current_id) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - TypeFromUser user_type (pvar_sp->GetTypeFromUser()); - - TypeFromParser parser_type (GuardedCopyType(user_type)); - - if (!parser_type.GetOpaqueQualType()) - { - if (log) - log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString()); - return; - } - - NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); - - pvar_sp->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = pvar_sp->GetParserVars(GetParserID()); - parser_vars->m_parser_type = parser_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value.Clear(); - - if (log) - { - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); - } -} - -void -ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, - const Symbol &symbol, - unsigned int current_id) -{ - assert(m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - - if (target == NULL) - return; - - ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); - - TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); - TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); - NamedDecl *var_decl = context.AddVarDecl(parser_type); - - std::string decl_name(context.m_decl_name.getAsString()); - ConstString entity_name(decl_name.c_str()); - ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), - entity_name, - user_type, - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - assert (entity.get()); - - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - - const Address symbol_address = symbol.GetAddress(); - lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); - - //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); - parser_vars->m_lldb_value.SetClangType(user_type); - parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); - - parser_vars->m_parser_type = parser_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_sym = &symbol; - - if (log) - { - ASTDumper ast_dumper(var_decl); - - log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString()); - } -} - -bool -ClangExpressionDeclMap::ResolveUnknownTypes() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - - ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); - - for (size_t index = 0, num_entities = m_found_entities.GetSize(); - index < num_entities; - ++index) - { - ClangExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); - - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - - if (entity->m_flags & ClangExpressionVariable::EVUnknownType) - { - const NamedDecl *named_decl = parser_vars->m_named_decl; - const VarDecl *var_decl = dyn_cast(named_decl); - - if (!var_decl) - { - if (log) - log->Printf("Entity of unknown type does not have a VarDecl"); - return false; - } - - if (log) - { - ASTDumper ast_dumper(const_cast(var_decl)); - log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString()); - } - - QualType var_type = var_decl->getType(); - TypeFromParser parser_type(var_type.getAsOpaquePtr(), &var_decl->getASTContext()); - - lldb::clang_type_t copied_type = m_ast_importer->CopyType(scratch_ast_context, &var_decl->getASTContext(), var_type.getAsOpaquePtr()); - - if (!copied_type) - { - if (log) - log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable"); - - return (bool) lldb::ClangExpressionVariableSP(); - } - - TypeFromUser user_type(copied_type, scratch_ast_context); - -// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); - parser_vars->m_lldb_value.SetClangType(user_type); - parser_vars->m_parser_type = parser_type; - - entity->SetClangType(user_type); - - entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); - } - } - - return true; -} - -void -ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, - const RegisterInfo *reg_info, - unsigned int current_id) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ClangASTType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context, - reg_info->encoding, - reg_info->byte_size * 8); - - if (!clang_type) - { - if (log) - log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str()); - return; - } - - TypeFromParser parser_clang_type (clang_type); - - NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); - - ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - assert (entity.get()); - - std::string decl_name(context.m_decl_name.getAsString()); - entity->SetName (ConstString (decl_name.c_str())); - entity->SetRegisterInfo (reg_info); - entity->EnableParserVars(GetParserID()); - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - parser_vars->m_parser_type = parser_clang_type; - parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; - parser_vars->m_lldb_value.Clear(); - entity->m_flags |= ClangExpressionVariable::EVBareRegister; - - if (log) - { - ASTDumper ast_dumper(var_decl); - log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString()); - } -} - -void -ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, - Function* function, - Symbol* symbol, - unsigned int current_id) -{ - assert (m_parser_vars.get()); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - NamedDecl *function_decl = NULL; - Address fun_address; - ClangASTType function_clang_type; - - bool is_indirect_function = false; - - if (function) - { - Type *function_type = function->GetType(); - - if (!function_type) - { - if (log) - log->PutCString(" Skipped a function because it has no type"); - return; - } - - function_clang_type = function_type->GetClangFullType(); - - if (!function_clang_type) - { - if (log) - log->PutCString(" Skipped a function because it has no Clang type"); - return; - } - - fun_address = function->GetAddressRange().GetBaseAddress(); - - ClangASTType copied_function_type = GuardedCopyType(function_clang_type); - if (copied_function_type) - { - function_decl = context.AddFunDecl(copied_function_type); - - if (!function_decl) - { - if (log) - { - log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", - function_type->GetName().GetCString(), - function_type->GetID()); - } - - return; - } - } - else - { - // We failed to copy the type we found - if (log) - { - log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt", - function_type->GetName().GetCString(), - function_type->GetID()); - } - - return; - } - } - else if (symbol) - { - fun_address = symbol->GetAddress(); - function_decl = context.AddGenericFunDecl(); - is_indirect_function = symbol->IsIndirect(); - } - else - { - if (log) - log->PutCString(" AddOneFunction called with no function and no symbol"); - return; - } - - Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - - lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); - - ClangExpressionVariableSP entity(m_found_entities.CreateVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), - m_parser_vars->m_target_info.byte_order, - m_parser_vars->m_target_info.address_byte_size)); - assert (entity.get()); - - std::string decl_name(context.m_decl_name.getAsString()); - entity->SetName(ConstString(decl_name.c_str())); - entity->SetClangType (function_clang_type); - entity->EnableParserVars(GetParserID()); - - ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); - - if (load_addr != LLDB_INVALID_ADDRESS) - { - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); - parser_vars->m_lldb_value.GetScalar() = load_addr; - } - else - { - // We have to try finding a file address. - - lldb::addr_t file_addr = fun_address.GetFileAddress(); - - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); - parser_vars->m_lldb_value.GetScalar() = file_addr; - } - - - parser_vars->m_named_decl = function_decl; - parser_vars->m_llvm_value = NULL; - - if (log) - { - ASTDumper ast_dumper(function_decl); - - StreamString ss; - - fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); - - log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", - current_id, - (function ? "specific" : "generic"), - decl_name.c_str(), - ss.GetData(), - ast_dumper.GetCString()); - } -} - -TypeFromParser -ClangExpressionDeclMap::CopyClassType(TypeFromUser &ut, - unsigned int current_id) -{ - ClangASTType copied_clang_type = GuardedCopyType(ut); - - if (!copied_clang_type) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("ClangExpressionDeclMap::CopyClassType - Couldn't import the type"); - - return TypeFromParser(); - } - - if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ()) - { - ClangASTType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); - ClangASTType void_ptr_clang_type = void_clang_type.GetPointerType(); - - ClangASTType method_type = ClangASTContext::CreateFunctionType (m_ast_context, - void_clang_type, - &void_ptr_clang_type, - 1, - false, - copied_clang_type.GetTypeQualifiers()); - - const bool is_virtual = false; - const bool is_static = false; - const bool is_inline = false; - const bool is_explicit = false; - const bool is_attr_used = true; - const bool is_artificial = false; - - copied_clang_type.AddMethodToCXXRecordType ("$__lldb_expr", - method_type, - lldb::eAccessPublic, - is_virtual, - is_static, - is_inline, - is_explicit, - is_attr_used, - is_artificial); - } - - return TypeFromParser(copied_clang_type); -} - -void -ClangExpressionDeclMap::AddOneType(NameSearchContext &context, - TypeFromUser &ut, - unsigned int current_id) -{ - ClangASTType copied_clang_type = GuardedCopyType(ut); - - if (!copied_clang_type) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type"); - - return; - } - - context.AddTypeDecl(copied_clang_type); -} diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp deleted file mode 100644 index 2b344b0c3733..000000000000 --- a/source/Expression/ClangExpressionParser.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//===-- ClangExpressionParser.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/Expression/ClangExpressionParser.h" - -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Disassembler.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRDynamicChecks.h" -#include "lldb/Expression/IRInterpreter.h" -#include "lldb/Host/File.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "clang/AST/ASTContext.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "clang/CodeGen/CodeGenAction.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/FrontendPluginRegistry.h" -#include "clang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Parse/ParseAST.h" -#include "clang/Rewrite/Frontend/FrontendActions.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" - -#include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/TargetSelect.h" - -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Signals.h" - -using namespace clang; -using namespace llvm; -using namespace lldb_private; - -//===----------------------------------------------------------------------===// -// Utility Methods for Clang -//===----------------------------------------------------------------------===// - -std::string GetBuiltinIncludePath(const char *Argv0) { - SmallString<128> P(llvm::sys::fs::getMainExecutable( - Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); - - if (!P.empty()) { - llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang - llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin - - // Get foo/lib/clang//include - llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, - "include"); - } - - return P.str(); -} - -class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks -{ - ClangModulesDeclVendor &m_decl_vendor; - ClangPersistentVariables &m_persistent_vars; - StreamString m_error_stream; - bool m_has_errors = false; -public: - LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, - ClangPersistentVariables &persistent_vars) : - m_decl_vendor(decl_vendor), - m_persistent_vars(persistent_vars) - { - } - - virtual void moduleImport(SourceLocation import_location, - ModuleIdPath path, - const clang::Module * /*null*/) - { - std::vector string_path; - - for (const std::pair &component : path) - { - string_path.push_back(ConstString(component.first->getName())); - } - - StreamString error_stream; - - ClangModulesDeclVendor::ModuleVector exported_modules; - - if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) - { - m_has_errors = true; - } - - for (ClangModulesDeclVendor::ModuleID module : exported_modules) - { - m_persistent_vars.AddHandLoadedClangModule(module); - } - } - - bool hasErrors() - { - return m_has_errors; - } - - const std::string &getErrorString() - { - return m_error_stream.GetString(); - } -}; - -//===----------------------------------------------------------------------===// -// Implementation of ClangExpressionParser -//===----------------------------------------------------------------------===// - -ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, - ClangExpression &expr, - bool generate_debug_info) : - m_expr (expr), - m_compiler (), - m_code_generator (), - m_pp_callbacks(nullptr) -{ - // 1. Create a new compiler instance. - m_compiler.reset(new CompilerInstance()); - - // 2. Install the target. - - lldb::TargetSP target_sp; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); - - // TODO: figure out what to really do when we don't have a valid target. - // Sometimes this will be ok to just use the host target triple (when we - // evaluate say "2+3", but other expressions like breakpoint conditions - // and other things that _are_ target specific really shouldn't just be - // using the host triple. This needs to be fixed in a better way. - if (target_sp && target_sp->GetArchitecture().IsValid()) - { - std::string triple = target_sp->GetArchitecture().GetTriple().str(); - m_compiler->getTargetOpts().Triple = triple; - } - else - { - m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); - } - - if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || - target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) - { - m_compiler->getTargetOpts().Features.push_back("+sse"); - m_compiler->getTargetOpts().Features.push_back("+sse2"); - } - - // Any arm32 iOS environment, but not on arm64 - if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && - m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && - m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) - { - m_compiler->getTargetOpts().ABI = "apcs-gnu"; - } - - m_compiler->createDiagnostics(); - - // Create the target instance. - m_compiler->setTarget(TargetInfo::CreateTargetInfo( - m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); - - assert (m_compiler->hasTarget()); - - // 3. Set options. - - lldb::LanguageType language = expr.Language(); - - switch (language) - { - case lldb::eLanguageTypeC: - break; - case lldb::eLanguageTypeObjC: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - break; - case lldb::eLanguageTypeC_plus_plus: - m_compiler->getLangOpts().CPlusPlus = true; - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - default: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - m_compiler->getLangOpts().CPlusPlus = true; - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; - break; - } - - m_compiler->getLangOpts().Bool = true; - m_compiler->getLangOpts().WChar = true; - m_compiler->getLangOpts().Blocks = true; - m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients - if (expr.DesiredResultType() == ClangExpression::eResultTypeId) - m_compiler->getLangOpts().DebuggerCastResultToId = true; - - m_compiler->getLangOpts().CharIsSigned = - ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); - - // Spell checking is a nice feature, but it ends up completing a - // lot of types that we didn't strictly speaking need to complete. - // As a result, we spend a long time parsing and importing debug - // information. - m_compiler->getLangOpts().SpellChecking = false; - - lldb::ProcessSP process_sp; - if (exe_scope) - process_sp = exe_scope->CalculateProcess(); - - if (process_sp && m_compiler->getLangOpts().ObjC1) - { - if (process_sp->GetObjCLanguageRuntime()) - { - if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2) - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); - else - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); - - if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) - m_compiler->getLangOpts().DebuggerObjCLiteral = true; - } - } - - m_compiler->getLangOpts().ThreadsafeStatics = false; - m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access - m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name - - // Set CodeGen options - m_compiler->getCodeGenOpts().EmitDeclMetadata = true; - m_compiler->getCodeGenOpts().InstrumentFunctions = false; - m_compiler->getCodeGenOpts().DisableFPElim = true; - m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; - if (generate_debug_info) - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); - else - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); - - // Disable some warnings. - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "unused-value", clang::diag::Severity::Ignored, SourceLocation()); - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "odr", clang::diag::Severity::Ignored, SourceLocation()); - - // Inform the target of the language options - // - // FIXME: We shouldn't need to do this, the target should be immutable once - // created. This complexity should be lifted elsewhere. - m_compiler->getTarget().adjust(m_compiler->getLangOpts()); - - // 4. Set up the diagnostic buffer for reporting errors - - m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); - - // 5. Set up the source management objects inside the compiler - - clang::FileSystemOptions file_system_options; - m_file_manager.reset(new clang::FileManager(file_system_options)); - - if (!m_compiler->hasSourceManager()) - m_compiler->createSourceManager(*m_file_manager.get()); - - m_compiler->createFileManager(); - m_compiler->createPreprocessor(TU_Complete); - - if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) - { - std::unique_ptr pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, target_sp->GetPersistentVariables())); - m_pp_callbacks = static_cast(pp_callbacks.get()); - m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); - } - - // 6. Most of this we get from the CompilerInstance, but we - // also want to give the context an ExternalASTSource. - m_selector_table.reset(new SelectorTable()); - m_builtin_context.reset(new Builtin::Context()); - - std::unique_ptr ast_context(new ASTContext(m_compiler->getLangOpts(), - m_compiler->getSourceManager(), - m_compiler->getPreprocessor().getIdentifierTable(), - *m_selector_table.get(), - *m_builtin_context.get())); - - ast_context->InitBuiltinTypes(m_compiler->getTarget()); - - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); - - if (decl_map) - { - llvm::IntrusiveRefCntPtr ast_source(decl_map->CreateProxy()); - decl_map->InstallASTContext(ast_context.get()); - ast_context->setExternalSource(ast_source); - } - - m_compiler->setASTContext(ast_context.release()); - - std::string module_name("$__lldb_module"); - - m_llvm_context.reset(new LLVMContext()); - m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), - module_name, - m_compiler->getHeaderSearchOpts(), - m_compiler->getPreprocessorOpts(), - m_compiler->getCodeGenOpts(), - *m_llvm_context)); -} - -ClangExpressionParser::~ClangExpressionParser() -{ -} - -unsigned -ClangExpressionParser::Parse (Stream &stream) -{ - TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); - - diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); - - const char *expr_text = m_expr.Text(); - - clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); - bool created_main_file = false; - if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) - { - std::string temp_source_path; - - int temp_fd = -1; - llvm::SmallString result_path; - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); - temp_source_path = std::move(tmpdir_file_spec.GetPath()); - llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); - } - else - { - llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); - } - - if (temp_fd != -1) - { - lldb_private::File file (temp_fd, true); - const size_t expr_text_len = strlen(expr_text); - size_t bytes_written = expr_text_len; - if (file.Write(expr_text, bytes_written).Success()) - { - if (bytes_written == expr_text_len) - { - file.Close(); - SourceMgr.setMainFileID(SourceMgr.createFileID( - m_file_manager->getFile(result_path), - SourceLocation(), SrcMgr::C_User)); - created_main_file = true; - } - } - } - } - - if (!created_main_file) - { - std::unique_ptr memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); - SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); - } - - diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); - - ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get()); - - if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap()) - decl_map->InstallCodeGenerator(m_code_generator.get()); - - if (ast_transformer) - ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); - else - ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); - - diag_buf->EndSourceFile(); - - TextDiagnosticBuffer::const_iterator diag_iterator; - - int num_errors = 0; - - if (m_pp_callbacks && m_pp_callbacks->hasErrors()) - { - num_errors++; - - stream.PutCString(m_pp_callbacks->getErrorString().c_str()); - } - - for (diag_iterator = diag_buf->warn_begin(); - diag_iterator != diag_buf->warn_end(); - ++diag_iterator) - stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); - - for (diag_iterator = diag_buf->err_begin(); - diag_iterator != diag_buf->err_end(); - ++diag_iterator) - { - num_errors++; - stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); - } - - for (diag_iterator = diag_buf->note_begin(); - diag_iterator != diag_buf->note_end(); - ++diag_iterator) - stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); - - if (!num_errors) - { - if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes()) - { - stream.Printf("error: Couldn't infer the type of a variable\n"); - num_errors++; - } - } - - return num_errors; -} - -static bool FindFunctionInModule (ConstString &mangled_name, - llvm::Module *module, - const char *orig_name) -{ - for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); - fi != fe; - ++fi) - { - if (fi->getName().str().find(orig_name) != std::string::npos) - { - mangled_name.SetCString(fi->getName().str().c_str()); - return true; - } - } - - return false; -} - -Error -ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, - lldb::addr_t &func_end, - std::shared_ptr &execution_unit_sp, - ExecutionContext &exe_ctx, - bool &can_interpret, - ExecutionPolicy execution_policy) -{ - func_addr = LLDB_INVALID_ADDRESS; - func_end = LLDB_INVALID_ADDRESS; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Error err; - - std::unique_ptr llvm_module_ap (m_code_generator->ReleaseModule()); - - if (!llvm_module_ap.get()) - { - err.SetErrorToGenericError(); - err.SetErrorString("IR doesn't contain a module"); - return err; - } - - // Find the actual name of the function (it's often mangled somehow) - - ConstString function_name; - - if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) - { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); - return err; - } - else - { - if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); - } - - execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here - llvm_module_ap, // handed off here - function_name, - exe_ctx.GetTargetSP(), - m_compiler->getTargetOpts().Features)); - - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL - - if (decl_map) - { - Stream *error_stream = NULL; - Target *target = exe_ctx.GetTargetPtr(); - if (target) - error_stream = target->GetDebugger().GetErrorFile().get(); - - IRForTarget ir_for_target(decl_map, - m_expr.NeedsVariableResolution(), - *execution_unit_sp, - error_stream, - function_name.AsCString()); - - bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); - - Error interpret_error; - Process *process = exe_ctx.GetProcessPtr(); - - bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); - can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); - - - if (!ir_can_run) - { - err.SetErrorString("The expression could not be prepared to run in the target"); - return err; - } - - if (!can_interpret && execution_policy == eExecutionPolicyNever) - { - err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); - return err; - } - - if (!process && execution_policy == eExecutionPolicyAlways) - { - err.SetErrorString("Expression needed to run in the target, but the target can't be run"); - return err; - } - - if (execution_policy == eExecutionPolicyAlways || !can_interpret) - { - if (m_expr.NeedsValidation() && process) - { - if (!process->GetDynamicCheckers()) - { - DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - - StreamString install_errors; - - if (!dynamic_checkers->Install(install_errors, exe_ctx)) - { - if (install_errors.GetString().empty()) - err.SetErrorString ("couldn't install checkers, unknown error"); - else - err.SetErrorString (install_errors.GetString().c_str()); - - return err; - } - - process->SetDynamicCheckers(dynamic_checkers); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); - } - - IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); - - if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) - { - err.SetErrorToGenericError(); - err.SetErrorString("Couldn't add dynamic checks to the expression"); - return err; - } - } - - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); - } - } - else - { - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); - } - - return err; -} - -bool -ClangExpressionParser::GetGenerateDebugInfo () const -{ - if (m_compiler) - return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo; - return false; -} diff --git a/source/Expression/ClangExpressionVariable.cpp b/source/Expression/ClangExpressionVariable.cpp deleted file mode 100644 index e86016e53a7d..000000000000 --- a/source/Expression/ClangExpressionVariable.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//===-- ClangExpressionVariable.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/Expression/ClangExpressionVariable.h" -#include "clang/AST/ASTContext.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/Value.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" - -using namespace lldb_private; -using namespace clang; - -ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) : - m_parser_vars(), - m_jit_vars (), - m_flags (EVNone), - m_frozen_sp (ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size)) -{ -} - -ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, - Value &value, - const ConstString &name, - uint16_t flags) : - m_parser_vars(), - m_jit_vars (), - m_flags (flags), - m_frozen_sp (ValueObjectConstResult::Create (exe_scope, value, name)) -{ -} - -ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : - m_parser_vars(), - m_jit_vars (), - m_flags (EVNone), - m_frozen_sp (valobj_sp) -{ -} - -//---------------------------------------------------------------------- -/// Return the variable's size in bytes -//---------------------------------------------------------------------- -size_t -ClangExpressionVariable::GetByteSize () -{ - return m_frozen_sp->GetByteSize(); -} - -const ConstString & -ClangExpressionVariable::GetName () -{ - return m_frozen_sp->GetName(); -} - -lldb::ValueObjectSP -ClangExpressionVariable::GetValueObject() -{ - return m_frozen_sp; -} - -RegisterInfo * -ClangExpressionVariable::GetRegisterInfo() -{ - return m_frozen_sp->GetValue().GetRegisterInfo(); -} - -void -ClangExpressionVariable::SetRegisterInfo (const RegisterInfo *reg_info) -{ - return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast(reg_info)); -} - -ClangASTType -ClangExpressionVariable::GetClangType() -{ - return m_frozen_sp->GetClangType(); -} - -void -ClangExpressionVariable::SetClangType(const ClangASTType &clang_type) -{ - m_frozen_sp->GetValue().SetClangType(clang_type); -} - - -TypeFromUser -ClangExpressionVariable::GetTypeFromUser() -{ - TypeFromUser tfu (m_frozen_sp->GetClangType()); - return tfu; -} - -uint8_t * -ClangExpressionVariable::GetValueBytes() -{ - const size_t byte_size = m_frozen_sp->GetByteSize(); - if (byte_size > 0) - { - if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) - { - m_frozen_sp->GetValue().ResizeData(byte_size); - m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor()); - } - return const_cast(m_frozen_sp->GetDataExtractor().GetDataStart()); - } - return NULL; -} - -void -ClangExpressionVariable::SetName (const ConstString &name) -{ - m_frozen_sp->SetName (name); -} - -void -ClangExpressionVariable::ValueUpdated () -{ - m_frozen_sp->ValueUpdated (); -} - -void -ClangExpressionVariable::TransferAddress (bool force) -{ - if (m_live_sp.get() == NULL) - return; - - if (m_frozen_sp.get() == NULL) - return; - - if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS)) - m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress()); -} diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp deleted file mode 100644 index b438dacdfabc..000000000000 --- a/source/Expression/ClangFunction.cpp +++ /dev/null @@ -1,596 +0,0 @@ -//===-- ClangFunction.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "clang/AST/ASTContext.h" -#include "clang/AST/RecordLayout.h" -#include "clang/CodeGen/CodeGenAction.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/IR/Module.h" - -// Project includes -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/State.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/ASTStructExtractor.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/Type.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlan.h" -#include "lldb/Target/ThreadPlanCallFunction.h" - -using namespace lldb_private; - -//---------------------------------------------------------------------- -// ClangFunction constructor -//---------------------------------------------------------------------- -ClangFunction::ClangFunction -( - ExecutionContextScope &exe_scope, - const ClangASTType &return_type, - const Address& functionAddress, - const ValueList &arg_value_list, - const char *name -) : - m_execution_unit_sp(), - m_parser(), - m_jit_module_wp(), - m_name (name ? name : ""), - m_function_ptr (NULL), - m_function_addr (functionAddress), - m_function_return_type(return_type), - m_wrapper_function_name ("__lldb_caller_function"), - m_wrapper_struct_name ("__lldb_caller_struct"), - m_wrapper_args_addrs (), - m_arg_values (arg_value_list), - m_compiled (false), - m_JITted (false) -{ - m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); - // Can't make a ClangFunction without a process. - assert (m_jit_process_wp.lock()); -} - -ClangFunction::ClangFunction -( - ExecutionContextScope &exe_scope, - Function &function, - ClangASTContext *ast_context, - const ValueList &arg_value_list, - const char *name -) : - m_name (name ? name : ""), - m_function_ptr (&function), - m_function_addr (), - m_function_return_type (), - m_wrapper_function_name ("__lldb_function_caller"), - m_wrapper_struct_name ("__lldb_caller_struct"), - m_wrapper_args_addrs (), - m_arg_values (arg_value_list), - m_compiled (false), - m_JITted (false) -{ - m_jit_process_wp = exe_scope.CalculateProcess(); - // Can't make a ClangFunction without a process. - assert (m_jit_process_wp.lock()); - - m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress(); - m_function_return_type = m_function_ptr->GetClangType().GetFunctionReturnType(); -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ClangFunction::~ClangFunction() -{ - lldb::ProcessSP process_sp (m_jit_process_wp.lock()); - if (process_sp) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } -} - -unsigned -ClangFunction::CompileFunction (Stream &errors) -{ - if (m_compiled) - return 0; - - // FIXME: How does clang tell us there's no return value? We need to handle that case. - unsigned num_errors = 0; - - std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); - - // Cons up the function we're going to wrap our call in, then compile it... - // We declare the function "extern "C"" because the compiler might be in C++ - // mode which would mangle the name and then we couldn't find it again... - m_wrapper_function_text.clear(); - m_wrapper_function_text.append ("extern \"C\" void "); - m_wrapper_function_text.append (m_wrapper_function_name); - m_wrapper_function_text.append (" (void *input)\n{\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" \n {\n"); - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" (*fn_ptr) ("); - - // Get the number of arguments. If we have a function type and it is prototyped, - // trust that, otherwise use the values we were given. - - // FIXME: This will need to be extended to handle Variadic functions. We'll need - // to pull the defined arguments out of the function, then add the types from the - // arguments list for the variable arguments. - - uint32_t num_args = UINT32_MAX; - bool trust_function = false; - // GetArgumentCount returns -1 for an unprototyped function. - ClangASTType function_clang_type; - if (m_function_ptr) - { - function_clang_type = m_function_ptr->GetClangType(); - if (function_clang_type) - { - int num_func_args = function_clang_type.GetFunctionArgumentCount(); - if (num_func_args >= 0) - { - trust_function = true; - num_args = num_func_args; - } - } - } - - if (num_args == UINT32_MAX) - num_args = m_arg_values.GetSize(); - - std::string args_buffer; // This one stores the definition of all the args in "struct caller". - std::string args_list_buffer; // This one stores the argument list called from the structure. - for (size_t i = 0; i < num_args; i++) - { - std::string type_name; - - if (trust_function) - { - type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); - } - else - { - ClangASTType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetClangType (); - if (clang_qual_type) - { - type_name = clang_qual_type.GetTypeName().AsCString(""); - } - else - { - errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); - return 1; - } - } - - m_wrapper_function_text.append (type_name); - if (i < num_args - 1) - m_wrapper_function_text.append (", "); - - char arg_buf[32]; - args_buffer.append (" "); - args_buffer.append (type_name); - snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); - args_buffer.push_back (' '); - args_buffer.append (arg_buf); - args_buffer.append (";\n"); - - args_list_buffer.append ("__lldb_fn_data->"); - args_list_buffer.append (arg_buf); - if (i < num_args - 1) - args_list_buffer.append (", "); - - } - m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. - - m_wrapper_function_text.append (args_buffer); - - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" return_value;"); - m_wrapper_function_text.append ("\n };\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" *) input;\n"); - - m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); - m_wrapper_function_text.append (args_list_buffer); - m_wrapper_function_text.append (");\n}\n"); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); - - // Okay, now compile this expression - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - if (jit_process_sp) - { - const bool generate_debug_info = true; - m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); - - num_errors = m_parser->Parse (errors); - } - else - { - errors.Printf("no process - unable to inject function"); - num_errors = 1; - } - - m_compiled = (num_errors == 0); - - if (!m_compiled) - return num_errors; - - return num_errors; -} - -bool -ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) -{ - Process *process = exe_ctx.GetProcessPtr(); - - if (!process) - return false; - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - - if (!m_compiled) - return false; - - if (m_JITted) - return true; - - bool can_interpret = false; // should stay that way - - Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - can_interpret, - eExecutionPolicyAlways)); - - if (!jit_error.Success()) - return false; - - if (m_parser->GetGenerateDebugInfo()) - { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - process->GetTarget().GetImages().Append(jit_module_sp); - } - } - if (process && m_jit_start_addr) - m_jit_process_wp = process->shared_from_this(); - - m_JITted = true; - - return true; -} - -bool -ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) -{ - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors); -} - -// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. - -bool -ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Address function_address, - ValueList &arg_values, - Stream &errors) -{ - // All the information to reconstruct the struct is provided by the - // StructExtractor. - if (!m_struct_valid) - { - errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); - return false; - } - - Error error; - using namespace clang; - lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == NULL) - return return_value; - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - - if (args_addr_ref == LLDB_INVALID_ADDRESS) - { - args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); - if (args_addr_ref == LLDB_INVALID_ADDRESS) - return false; - m_wrapper_args_addrs.push_back (args_addr_ref); - } - else - { - // Make sure this is an address that we've already handed out. - if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) - { - return false; - } - } - - // TODO: verify fun_addr needs to be a callable address - Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); - uint64_t first_offset = m_member_offsets[0]; - process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); - - // FIXME: We will need to extend this for Variadic functions. - - Error value_error; - - size_t num_args = arg_values.GetSize(); - if (num_args != m_arg_values.GetSize()) - { - errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); - return false; - } - - for (size_t i = 0; i < num_args; i++) - { - // FIXME: We should sanity check sizes. - - uint64_t offset = m_member_offsets[i+1]; // Clang sizes are in bytes. - Value *arg_value = arg_values.GetValueAtIndex(i); - - // FIXME: For now just do scalars: - - // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) - - if (arg_value->GetValueType() == Value::eValueTypeHostAddress && - arg_value->GetContextType() == Value::eContextTypeInvalid && - arg_value->GetClangType().IsPointerType()) - continue; - - const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); - - if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) - return false; - } - - return true; -} - -bool -ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) -{ - using namespace clang; - - if (CompileFunction(errors) != 0) - return false; - if (!WriteFunctionWrapper(exe_ctx, errors)) - return false; - if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors)) - return false; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref); - - return true; -} - -lldb::ThreadPlanSP -ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, - const EvaluateExpressionOptions &options, - Stream &errors) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (log) - log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); - - // FIXME: Use the errors Stream for better error reporting. - Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) - { - errors.Printf("Can't call a function without a valid thread."); - return NULL; - } - - // Okay, now run the function: - - Address wrapper_address (m_jit_start_addr); - - lldb::addr_t args = { args_addr }; - - lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread, - wrapper_address, - ClangASTType(), - args, - options)); - new_plan_sp->SetIsMasterPlan(true); - new_plan_sp->SetOkayToDiscard (false); - return new_plan_sp; -} - -bool -ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) -{ - // Read the return value - it is the last field in the struct: - // FIXME: How does clang tell us there's no return value? We need to handle that case. - // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject - // to fetch the value. That way we can fetch any values we need. - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (log) - log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == NULL) - return false; - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - - if (process != jit_process_sp.get()) - return false; - - Error error; - ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error); - - if (error.Fail()) - return false; - - ret_value.SetClangType(m_function_return_type); - ret_value.SetValueType(Value::eValueTypeScalar); - return true; -} - -void -ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) -{ - std::list::iterator pos; - pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr); - if (pos != m_wrapper_args_addrs.end()) - m_wrapper_args_addrs.erase(pos); - - exe_ctx.GetProcessRef().DeallocateMemory(args_addr); -} - -lldb::ExpressionResults -ClangFunction::ExecuteFunction( - ExecutionContext &exe_ctx, - lldb::addr_t *args_addr_ptr, - const EvaluateExpressionOptions &options, - Stream &errors, - Value &results) -{ - using namespace clang; - lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - - // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore - // breakpoints, unwind on error, and don't try to debug it. - EvaluateExpressionOptions real_options = options; - real_options.SetDebug(false); - real_options.SetUnwindOnError(true); - real_options.SetIgnoreBreakpoints(true); - - lldb::addr_t args_addr; - - if (args_addr_ptr != NULL) - args_addr = *args_addr_ptr; - else - args_addr = LLDB_INVALID_ADDRESS; - - if (CompileFunction(errors) != 0) - return lldb::eExpressionSetupError; - - if (args_addr == LLDB_INVALID_ADDRESS) - { - if (!InsertFunction(exe_ctx, args_addr, errors)) - return lldb::eExpressionSetupError; - } - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (log) - log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); - - lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, - args_addr, - real_options, - errors); - if (!call_plan_sp) - return lldb::eExpressionSetupError; - - // We need to make sure we record the fact that we are running an expression here - // otherwise this fact will fail to be recorded when fetching an Objective-C object description - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, - call_plan_sp, - real_options, - errors); - - if (log) - { - if (return_value != lldb::eExpressionCompleted) - { - log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); - } - else - { - log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); - } - } - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - if (args_addr_ptr != NULL) - *args_addr_ptr = args_addr; - - if (return_value != lldb::eExpressionCompleted) - return return_value; - - FetchFunctionResults(exe_ctx, args_addr, results); - - if (args_addr_ptr == NULL) - DeallocateFunctionResults(exe_ctx, args_addr); - - return lldb::eExpressionCompleted; -} - -clang::ASTConsumer * -ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough) -{ - m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this)); - - return m_struct_extractor.get(); -} diff --git a/source/Expression/ClangModulesDeclVendor.cpp b/source/Expression/ClangModulesDeclVendor.cpp deleted file mode 100644 index e8253630724a..000000000000 --- a/source/Expression/ClangModulesDeclVendor.cpp +++ /dev/null @@ -1,731 +0,0 @@ -//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include // std::once - -#include "lldb/Expression/ClangModulesDeclVendor.h" - -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/LLDBAssert.h" - -#include "clang/Basic/TargetInfo.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Parse/Parser.h" -#include "clang/Sema/Lookup.h" -#include "clang/Serialization/ASTReader.h" - - -using namespace lldb_private; - -namespace { - // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings - // so we can provide them to the user in case a module failed to load. - class StoringDiagnosticConsumer : public clang::DiagnosticConsumer - { - public: - StoringDiagnosticConsumer (); - void - HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info); - - void - ClearDiagnostics (); - - void - DumpDiagnostics (Stream &error_stream); - private: - typedef std::pair IDAndDiagnostic; - std::vector m_diagnostics; - Log * m_log; - }; - - // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required - // to load modules. - class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor - { - public: - ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, - llvm::IntrusiveRefCntPtr &compiler_invocation, - std::unique_ptr &&compiler_instance, - std::unique_ptr &&parser); - - virtual bool - AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) override; - - virtual bool - AddModulesForCompileUnit(CompileUnit &cu, - ModuleVector &exported_modules, - Stream &error_stream) override; - - virtual uint32_t - FindDecls (const ConstString &name, - bool append, - uint32_t max_matches, - std::vector &decls) override; - - virtual void - ForEachMacro(const ModuleVector &modules, - std::function handler) override; - - ~ClangModulesDeclVendorImpl(); - - private: - void - ReportModuleExportsHelper (std::set &exports, - clang::Module *module); - - void - ReportModuleExports (ModuleVector &exports, - clang::Module *module); - - clang::ModuleLoadResult - DoGetModule(clang::ModuleIdPath path, bool make_visible); - - bool m_enabled = false; - - llvm::IntrusiveRefCntPtr m_diagnostics_engine; - llvm::IntrusiveRefCntPtr m_compiler_invocation; - std::unique_ptr m_compiler_instance; - std::unique_ptr m_parser; - size_t m_source_location_index = 0; // used to give name components fake SourceLocations - - typedef std::vector ImportedModule; - typedef std::map ImportedModuleMap; - typedef std::set ImportedModuleSet; - ImportedModuleMap m_imported_modules; - ImportedModuleSet m_user_imported_modules; - }; -} - -StoringDiagnosticConsumer::StoringDiagnosticConsumer () -{ - m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); -} - -void -StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) -{ - llvm::SmallVector diagnostic_string; - - info.FormatDiagnostic(diagnostic_string); - - m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); -} - -void -StoringDiagnosticConsumer::ClearDiagnostics () -{ - m_diagnostics.clear(); -} - -void -StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) -{ - for (IDAndDiagnostic &diag : m_diagnostics) - { - switch (diag.first) - { - default: - error_stream.PutCString(diag.second.c_str()); - error_stream.PutChar('\n'); - break; - case clang::DiagnosticsEngine::Level::Ignored: - break; - } - } -} - -static FileSpec -GetResourceDir () -{ - static FileSpec g_cached_resource_dir; - - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, [](){ - HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); - }); - - return g_cached_resource_dir; -} - - -ClangModulesDeclVendor::ClangModulesDeclVendor() -{ -} - -ClangModulesDeclVendor::~ClangModulesDeclVendor() -{ -} - -ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, - llvm::IntrusiveRefCntPtr &compiler_invocation, - std::unique_ptr &&compiler_instance, - std::unique_ptr &&parser) : - ClangModulesDeclVendor(), - m_diagnostics_engine(diagnostics_engine), - m_compiler_invocation(compiler_invocation), - m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)), - m_imported_modules() -{ -} - -void -ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set &exports, - clang::Module *module) -{ - if (exports.count(reinterpret_cast(module))) - return; - - exports.insert(reinterpret_cast(module)); - - llvm::SmallVector sub_exports; - - module->getExportedModules(sub_exports); - - for (clang::Module *module : sub_exports) - { - ReportModuleExportsHelper(exports, module); - } -} - -void -ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports, - clang::Module *module) -{ - std::set exports_set; - - ReportModuleExportsHelper(exports_set, module); - - for (ModuleID module : exports_set) - { - exports.push_back(module); - } -} - -bool -ClangModulesDeclVendorImpl::AddModule(ModulePath &path, - ModuleVector *exported_modules, - Stream &error_stream) -{ - // Fail early. - - if (m_compiler_instance->hadModuleLoaderFatalFailure()) - { - error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); - return false; - } - - // Check if we've already imported this module. - - std::vector imported_module; - - for (ConstString path_component : path) - { - imported_module.push_back(path_component); - } - - { - ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); - - if (mi != m_imported_modules.end()) - { - if (exported_modules) - { - ReportModuleExports(*exported_modules, mi->second); - } - return true; - } - } - - if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef())) - { - error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString()); - return false; - } - - llvm::SmallVector, 4> clang_path; - - { - clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); - - for (ConstString path_component : path) - { - clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()), - source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++))); - } - } - - StoringDiagnosticConsumer *diagnostic_consumer = static_cast(m_compiler_instance->getDiagnostics().getClient()); - - diagnostic_consumer->ClearDiagnostics(); - - clang::Module *top_level_module = DoGetModule(clang_path.front(), false); - - if (!top_level_module) - { - diagnostic_consumer->DumpDiagnostics(error_stream); - error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString()); - return false; - } - - clang::Module *submodule = top_level_module; - - for (size_t ci = 1; ci < path.size(); ++ci) - { - llvm::StringRef component = path[ci].GetStringRef(); - submodule = submodule->findSubmodule(component.str()); - if (!submodule) - { - diagnostic_consumer->DumpDiagnostics(error_stream); - error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); - return false; - } - } - - clang::Module *requested_module = DoGetModule(clang_path, true); - - if (requested_module != nullptr) - { - if (exported_modules) - { - ReportModuleExports(*exported_modules, requested_module); - } - - m_imported_modules[imported_module] = requested_module; - - m_enabled = true; - - return true; - } - - return false; -} - - -bool -ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language) -{ - switch (language) - { - default: - return false; - // C++ and friends to be added - case lldb::LanguageType::eLanguageTypeC: - case lldb::LanguageType::eLanguageTypeC11: - case lldb::LanguageType::eLanguageTypeC89: - case lldb::LanguageType::eLanguageTypeC99: - case lldb::LanguageType::eLanguageTypeObjC: - return true; - } -} - -bool -ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu, - ClangModulesDeclVendor::ModuleVector &exported_modules, - Stream &error_stream) -{ - if (LanguageSupportsClangModules(cu.GetLanguage())) - { - std::vector imported_modules = cu.GetImportedModules(); - - for (ConstString imported_module : imported_modules) - { - std::vector path; - - path.push_back(imported_module); - - if (!AddModule(path, &exported_modules, error_stream)) - { - return false; - } - } - - return true; - } - - return true; -} - -// ClangImporter::lookupValue - -uint32_t -ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, - bool append, - uint32_t max_matches, - std::vector &decls) -{ - if (!m_enabled) - { - return 0; - } - - if (!append) - decls.clear(); - - clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); - - clang::LookupResult lookup_result(m_compiler_instance->getSema(), - clang::DeclarationName(&ident), - clang::SourceLocation(), - clang::Sema::LookupOrdinaryName); - - m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); - - uint32_t num_matches = 0; - - for (clang::NamedDecl *named_decl : lookup_result) - { - if (num_matches >= max_matches) - return num_matches; - - decls.push_back(named_decl); - ++num_matches; - } - - return num_matches; -} - -void -ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules, - std::function handler) -{ - if (!m_enabled) - { - return; - } - - typedef std::map ModulePriorityMap; - ModulePriorityMap module_priorities; - - ssize_t priority = 0; - - for (ModuleID module : modules) - { - module_priorities[module] = priority++; - } - - if (m_compiler_instance->getPreprocessor().getExternalSource()) - { - m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros(); - } - - for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(), - me = m_compiler_instance->getPreprocessor().macro_end(); - mi != me; - ++mi) - { - const clang::IdentifierInfo *ii = nullptr; - - { - if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup()) - { - lookup->get(mi->first->getName()); - } - if (!ii) - { - ii = mi->first; - } - } - - ssize_t found_priority = -1; - clang::MacroInfo *macro_info = nullptr; - - for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) - { - clang::Module *module = module_macro->getOwningModule(); - - { - ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(module)); - - if (pi != module_priorities.end() && pi->second > found_priority) - { - macro_info = module_macro->getMacroInfo(); - found_priority = pi->second; - } - } - - clang::Module *top_level_module = module->getTopLevelModule(); - - if (top_level_module != module) - { - ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(top_level_module)); - - if ((pi != module_priorities.end()) && pi->second > found_priority) - { - macro_info = module_macro->getMacroInfo(); - found_priority = pi->second; - } - } - } - - if (macro_info) - { - std::string macro_expansion = "#define "; - macro_expansion.append(mi->first->getName().str().c_str()); - - { - if (macro_info->isFunctionLike()) - { - macro_expansion.append("("); - - bool first_arg = true; - - for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), - ae = macro_info->arg_end(); - ai != ae; - ++ai) - { - if (!first_arg) - { - macro_expansion.append(", "); - } - else - { - first_arg = false; - } - - macro_expansion.append((*ai)->getName().str()); - } - - if (macro_info->isC99Varargs()) - { - if (first_arg) - { - macro_expansion.append("..."); - } - else - { - macro_expansion.append(", ..."); - } - } - else if (macro_info->isGNUVarargs()) - { - macro_expansion.append("..."); - } - - macro_expansion.append(")"); - } - - macro_expansion.append(" "); - - bool first_token = true; - - for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), - te = macro_info->tokens_end(); - ti != te; - ++ti) - { - if (!first_token) - { - macro_expansion.append(" "); - } - else - { - first_token = false; - } - - if (ti->isLiteral()) - { - if (const char *literal_data = ti->getLiteralData()) - { - std::string token_str(literal_data, ti->getLength()); - macro_expansion.append(token_str); - } - else - { - bool invalid = false; - const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid); - - if (invalid) - { - lldbassert(!"Unhandled token kind"); - macro_expansion.append(""); - } - else - { - macro_expansion.append(std::string(literal_source, ti->getLength())); - } - } - } - else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind())) - { - macro_expansion.append(punctuator_spelling); - } - else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind())) - { - macro_expansion.append(keyword_spelling); - } - else - { - switch (ti->getKind()) - { - case clang::tok::TokenKind::identifier: - macro_expansion.append(ti->getIdentifierInfo()->getName().str()); - break; - case clang::tok::TokenKind::raw_identifier: - macro_expansion.append(ti->getRawIdentifier().str()); - default: - macro_expansion.append(ti->getName()); - break; - } - } - } - - if (handler(macro_expansion)) - { - return; - } - } - } - } -} - -ClangModulesDeclVendorImpl::~ClangModulesDeclVendorImpl() -{ -} - -clang::ModuleLoadResult -ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, - bool make_visible) -{ - clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; - - const bool is_inclusion_directive = false; - - return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); -} - -static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; - -lldb_private::ClangModulesDeclVendor * -ClangModulesDeclVendor::Create(Target &target) -{ - // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's - // compiler are both initialized in the same way – preferably by the same code. - - if (!target.GetPlatform()->SupportsModules()) - return nullptr; - - const ArchSpec &arch = target.GetArchitecture(); - - std::vector compiler_invocation_arguments = - { - "-fmodules", - "-fcxx-modules", - "-fsyntax-only", - "-femit-all-decls", - "-target", arch.GetTriple().str(), - "-fmodules-validate-system-headers", - "-Werror=non-modular-include-in-framework-module" - }; - - target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); - - compiler_invocation_arguments.push_back(ModuleImportBufferName); - - // Add additional search paths with { "-I", path } or { "-F", path } here. - - { - llvm::SmallString<128> DefaultModuleCache; - const bool erased_on_reboot = false; - llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); - llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); - std::string module_cache_argument("-fmodules-cache-path="); - module_cache_argument.append(DefaultModuleCache.str().str()); - compiler_invocation_arguments.push_back(module_cache_argument); - } - - FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); - - for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) - { - const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); - - std::string search_path_argument = "-I"; - search_path_argument.append(search_path.GetPath()); - - compiler_invocation_arguments.push_back(search_path_argument); - } - - { - FileSpec clang_resource_dir = GetResourceDir(); - - if (clang_resource_dir.IsDirectory()) - { - compiler_invocation_arguments.push_back("-resource-dir"); - compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); - } - } - - llvm::IntrusiveRefCntPtr diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, - new StoringDiagnosticConsumer); - - std::vector compiler_invocation_argument_cstrs; - - for (const std::string &arg : compiler_invocation_arguments) { - compiler_invocation_argument_cstrs.push_back(arg.c_str()); - } - - llvm::IntrusiveRefCntPtr invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); - - if (!invocation) - return nullptr; - - std::unique_ptr source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", - ModuleImportBufferName); - - invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); - - std::unique_ptr instance(new clang::CompilerInstance); - - instance->setDiagnostics(diagnostics_engine.get()); - instance->setInvocation(invocation.get()); - - std::unique_ptr action(new clang::SyntaxOnlyAction); - - instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); - - if (!instance->hasTarget()) - return nullptr; - - instance->getTarget().adjust(instance->getLangOpts()); - - if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) - return nullptr; - - instance->getPreprocessor().enableIncrementalProcessing(); - - instance->createModuleManager(); - - instance->createSema(action->getTranslationUnitKind(), nullptr); - - const bool skipFunctionBodies = false; - std::unique_ptr parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); - - instance->getPreprocessor().EnterMainSourceFile(); - parser->Initialize(); - - clang::Parser::DeclGroupPtrTy parsed; - - while (!parser->ParseTopLevelDecl(parsed)); - - return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); -} diff --git a/source/Expression/ClangPersistentVariables.cpp b/source/Expression/ClangPersistentVariables.cpp deleted file mode 100644 index db062d2e20b6..000000000000 --- a/source/Expression/ClangPersistentVariables.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===-- ClangPersistentVariables.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/Expression/ClangPersistentVariables.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/Value.h" - -#include "llvm/ADT/StringMap.h" - -using namespace lldb; -using namespace lldb_private; - -ClangPersistentVariables::ClangPersistentVariables () : - ClangExpressionVariableList(), - m_next_persistent_variable_id (0) -{ -} - -ClangExpressionVariableSP -ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) -{ - ClangExpressionVariableSP var_sp (CreateVariable(valobj_sp)); - return var_sp; -} - -ClangExpressionVariableSP -ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope, - const ConstString &name, - const TypeFromUser& user_type, - lldb::ByteOrder byte_order, - uint32_t addr_byte_size) -{ - ClangExpressionVariableSP var_sp (GetVariable(name)); - - if (!var_sp) - var_sp = CreateVariable(exe_scope, name, user_type, byte_order, addr_byte_size); - - return var_sp; -} - -void -ClangPersistentVariables::RemovePersistentVariable (lldb::ClangExpressionVariableSP variable) -{ - RemoveVariable(variable); - - const char *name = variable->GetName().AsCString(); - - if (*name != '$') - return; - name++; - - if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) - m_next_persistent_variable_id--; -} - -ConstString -ClangPersistentVariables::GetNextPersistentVariableName () -{ - char name_cstr[256]; - ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++); - ConstString name(name_cstr); - return name; -} - -void -ClangPersistentVariables::RegisterPersistentType (const ConstString &name, - clang::TypeDecl *type_decl) -{ - m_persistent_types.insert(std::pair(name.GetCString(), type_decl)); -} - -clang::TypeDecl * -ClangPersistentVariables::GetPersistentType (const ConstString &name) -{ - PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString()); - - if (i == m_persistent_types.end()) - return NULL; - else - return i->second; -} diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp deleted file mode 100644 index 0da70e2b0a70..000000000000 --- a/source/Expression/ClangUserExpression.cpp +++ /dev/null @@ -1,1172 +0,0 @@ -//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include -#if HAVE_SYS_TYPES_H -# include -#endif - -#include -#include -#include - -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Expression/ASTResultSynthesizer.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Expression/ExpressionSourceCode.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRInterpreter.h" -#include "lldb/Expression/Materializer.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Symbol/Type.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" -#include "lldb/Symbol/VariableList.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/ThreadPlan.h" -#include "lldb/Target/ThreadPlanCallUserExpression.h" - -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" - -using namespace lldb_private; - -ClangUserExpression::ClangUserExpression (const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type) : - ClangExpression (), - m_stack_frame_bottom (LLDB_INVALID_ADDRESS), - m_stack_frame_top (LLDB_INVALID_ADDRESS), - m_expr_text (expr), - m_expr_prefix (expr_prefix ? expr_prefix : ""), - m_language (language), - m_transformed_text (), - m_desired_type (desired_type), - m_expr_decl_map(), - m_execution_unit_sp(), - m_materializer_ap(), - m_result_synthesizer(), - m_jit_module_wp(), - m_enforce_valid_object (true), - m_in_cplusplus_method (false), - m_in_objectivec_method (false), - m_in_static_method(false), - m_needs_object_ptr (false), - m_const_object (false), - m_target (NULL), - m_can_interpret (false), - m_materialized_address (LLDB_INVALID_ADDRESS) -{ - switch (m_language) - { - case lldb::eLanguageTypeC_plus_plus: - m_allow_cxx = true; - break; - case lldb::eLanguageTypeObjC: - m_allow_objc = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - default: - m_allow_cxx = true; - m_allow_objc = true; - break; - } -} - -ClangUserExpression::~ClangUserExpression () -{ - if (m_target) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - m_target->GetImages().Remove(jit_module_sp); - } -} - -clang::ASTConsumer * -ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) -{ - m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough, - *m_target)); - - return m_result_synthesizer.get(); -} - -void -ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("ClangUserExpression::ScanContext()"); - - m_target = exe_ctx.GetTargetPtr(); - - if (!(m_allow_cxx || m_allow_objc)) - { - if (log) - log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); - return; - } - - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) - { - if (log) - log->Printf(" [CUE::SC] Null stack frame"); - return; - } - - SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); - - if (!sym_ctx.function) - { - if (log) - log->Printf(" [CUE::SC] Null function"); - return; - } - - // Find the block that defines the function represented by "sym_ctx" - Block *function_block = sym_ctx.GetFunctionBlock(); - - if (!function_block) - { - if (log) - log->Printf(" [CUE::SC] Null function block"); - return; - } - - clang::DeclContext *decl_context = function_block->GetClangDeclContext(); - - if (!decl_context) - { - if (log) - log->Printf(" [CUE::SC] Null decl context"); - return; - } - - if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast(decl_context)) - { - if (m_allow_cxx && method_decl->isInstance()) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(thisErrorString); - return; - } - - lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - - if (!this_var_sp || - !this_var_sp->IsInScope(frame) || - !this_var_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(thisErrorString); - return; - } - } - - m_in_cplusplus_method = true; - m_needs_object_ptr = true; - } - } - else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast(decl_context)) - { - if (m_allow_objc) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(selfErrorString); - return; - } - - lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - - if (!self_variable_sp || - !self_variable_sp->IsInScope(frame) || - !self_variable_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(selfErrorString); - return; - } - } - - m_in_objectivec_method = true; - m_needs_object_ptr = true; - - if (!method_decl->isInstanceMethod()) - m_in_static_method = true; - } - } - else if (clang::FunctionDecl *function_decl = llvm::dyn_cast(decl_context)) - { - // We might also have a function that said in the debug information that it captured an - // object pointer. The best way to deal with getting to the ivars at present is by pretending - // that this is a method of a class in whatever runtime the debug info says the object pointer - // belongs to. Do that here. - - ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl); - if (metadata && metadata->HasObjectPtr()) - { - lldb::LanguageType language = metadata->GetObjectPtrLanguage(); - if (language == lldb::eLanguageTypeC_plus_plus) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(thisErrorString); - return; - } - - lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - - if (!this_var_sp || - !this_var_sp->IsInScope(frame) || - !this_var_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(thisErrorString); - return; - } - } - - m_in_cplusplus_method = true; - m_needs_object_ptr = true; - } - else if (language == lldb::eLanguageTypeObjC) - { - if (m_enforce_valid_object) - { - lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - - const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; - - if (!variable_list_sp) - { - err.SetErrorString(selfErrorString); - return; - } - - lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - - if (!self_variable_sp || - !self_variable_sp->IsInScope(frame) || - !self_variable_sp->LocationIsValidForFrame (frame)) - { - err.SetErrorString(selfErrorString); - return; - } - - Type *self_type = self_variable_sp->GetType(); - - if (!self_type) - { - err.SetErrorString(selfErrorString); - return; - } - - ClangASTType self_clang_type = self_type->GetClangForwardType(); - - if (!self_clang_type) - { - err.SetErrorString(selfErrorString); - return; - } - - if (self_clang_type.IsObjCClassType()) - { - return; - } - else if (self_clang_type.IsObjCObjectPointerType()) - { - m_in_objectivec_method = true; - m_needs_object_ptr = true; - } - else - { - err.SetErrorString(selfErrorString); - return; - } - } - else - { - m_in_objectivec_method = true; - m_needs_object_ptr = true; - } - } - } - } -} - -void -ClangUserExpression::InstallContext (ExecutionContext &exe_ctx) -{ - m_process_wp = exe_ctx.GetProcessSP(); - - lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); - - if (frame_sp) - m_address = frame_sp->GetFrameCodeAddress(); -} - -bool -ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, - lldb::TargetSP &target_sp, - lldb::ProcessSP &process_sp, - lldb::StackFrameSP &frame_sp) -{ - lldb::ProcessSP expected_process_sp = m_process_wp.lock(); - process_sp = exe_ctx.GetProcessSP(); - - if (process_sp != expected_process_sp) - return false; - - process_sp = exe_ctx.GetProcessSP(); - target_sp = exe_ctx.GetTargetSP(); - frame_sp = exe_ctx.GetFrameSP(); - - if (m_address.IsValid()) - { - if (!frame_sp) - return false; - else - return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); - } - - return true; -} - -bool -ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx) -{ - lldb::TargetSP target_sp; - lldb::ProcessSP process_sp; - lldb::StackFrameSP frame_sp; - - return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); -} - -// This is a really nasty hack, meant to fix Objective-C expressions of the form -// (int)[myArray count]. Right now, because the type information for count is -// not available, [myArray count] returns id, which can't be directly cast to -// int without causing a clang error. -static void -ApplyObjcCastHack(std::string &expr) -{ -#define OBJC_CAST_HACK_FROM "(int)[" -#define OBJC_CAST_HACK_TO "(int)(long long)[" - - size_t from_offset; - - while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) - expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); - -#undef OBJC_CAST_HACK_TO -#undef OBJC_CAST_HACK_FROM -} - -// Another hack, meant to allow use of unichar despite it not being available in -// the type information. Although we could special-case it in type lookup, -// hopefully we'll figure out a way to #include the same environment as is -// present in the original source file rather than try to hack specific type -// definitions in as needed. -//static void -//ApplyUnicharHack(std::string &expr) -//{ -//#define UNICHAR_HACK_FROM "unichar" -//#define UNICHAR_HACK_TO "unsigned short" -// -// size_t from_offset; -// -// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos) -// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO); -// -//#undef UNICHAR_HACK_TO -//#undef UNICHAR_HACK_FROM -//} - -bool -ClangUserExpression::Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Error err; - - InstallContext(exe_ctx); - - ScanContext(exe_ctx, err); - - if (!err.Success()) - { - error_stream.Printf("warning: %s\n", err.AsCString()); - } - - StreamString m_transformed_stream; - - //////////////////////////////////// - // Generate the expression - // - - ApplyObjcCastHack(m_expr_text); - //ApplyUnicharHack(m_expr_text); - - std::string prefix = m_expr_prefix; - - if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) - { - const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = m_target->GetPersistentVariables().GetHandLoadedClangModules(); - ClangModulesDeclVendor::ModuleVector modules_for_macros; - - for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) - { - modules_for_macros.push_back(module); - } - - if (m_target->GetEnableAutoImportClangModules()) - { - if (StackFrame *frame = exe_ctx.GetFramePtr()) - { - if (Block *block = frame->GetFrameBlock()) - { - SymbolContext sc; - - block->CalculateSymbolContext(&sc); - - if (sc.comp_unit) - { - StreamString error_stream; - - decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); - } - } - } - } - } - - std::unique_ptr source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); - - lldb::LanguageType lang_type; - - if (m_in_cplusplus_method) - lang_type = lldb::eLanguageTypeC_plus_plus; - else if (m_in_objectivec_method) - lang_type = lldb::eLanguageTypeObjC; - else - lang_type = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) - { - error_stream.PutCString ("error: couldn't construct expression body"); - return false; - } - - if (log) - log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); - - //////////////////////////////////// - // Set up the target and compiler - // - - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - { - error_stream.PutCString ("error: invalid target\n"); - return false; - } - - ////////////////////////// - // Parse the expression - // - - m_materializer_ap.reset(new Materializer()); - - m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); - - class OnExit - { - public: - typedef std::function Callback; - - OnExit (Callback const &callback) : - m_callback(callback) - { - } - - ~OnExit () - { - m_callback(); - } - private: - Callback m_callback; - }; - - OnExit on_exit([this]() { m_expr_decl_map.reset(); }); - - if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get())) - { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); - - m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. - - return false; - } - - Process *process = exe_ctx.GetProcessPtr(); - ExecutionContextScope *exe_scope = process; - - if (!exe_scope) - exe_scope = exe_ctx.GetTargetPtr(); - - ClangExpressionParser parser(exe_scope, *this, generate_debug_info); - - unsigned num_errors = parser.Parse (error_stream); - - if (num_errors) - { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - - m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. - - return false; - } - - ////////////////////////////////////////////////////////////////////////////////////////// - // Prepare the output of the parser for execution, evaluating it statically if possible - // - - Error jit_error = parser.PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - m_can_interpret, - execution_policy); - - if (generate_debug_info) - { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - target->GetImages().Append(jit_module_sp); - } -// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); -// StreamFile strm (stdout, false); -// if (jit_obj_file) -// { -// jit_obj_file->GetSectionList(); -// jit_obj_file->GetSymtab(); -// jit_obj_file->Dump(&strm); -// } -// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); -// if (jit_sym_vendor) -// { -// lldb_private::SymbolContextList sc_list; -// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); -// sc_list.Dump(&strm, target); -// jit_sym_vendor->Dump(&strm); -// } - } - - m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. - - if (jit_error.Success()) - { - if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) - m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); - return true; - } - else - { - const char *error_cstr = jit_error.AsCString(); - if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); - else - error_stream.Printf ("error: expression can't be interpreted or run\n"); - return false; - } -} - -static lldb::addr_t -GetObjectPointer (lldb::StackFrameSP frame_sp, - ConstString &object_name, - Error &err) -{ - err.Clear(); - - if (!frame_sp) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } - - lldb::VariableSP var_sp; - lldb::ValueObjectSP valobj_sp; - - valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), - lldb::eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsNoFragileObjcIvar | - StackFrame::eExpressionPathOptionsNoSyntheticChildren | - StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, - var_sp, - err); - - if (!err.Success() || !valobj_sp.get()) - return LLDB_INVALID_ADDRESS; - - lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - - if (ret == LLDB_INVALID_ADDRESS) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } - - return ret; -} - -bool -ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::addr_t &struct_address, - lldb::addr_t &object_ptr, - lldb::addr_t &cmd_ptr) -{ - lldb::TargetSP target; - lldb::ProcessSP process; - lldb::StackFrameSP frame; - - if (!LockAndCheckContext(exe_ctx, - target, - process, - frame)) - { - error_stream.Printf("The context has changed before we could JIT the expression!\n"); - return false; - } - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { - if (m_needs_object_ptr) - { - ConstString object_name; - - if (m_in_cplusplus_method) - { - object_name.SetCString("this"); - } - else if (m_in_objectivec_method) - { - object_name.SetCString("self"); - } - else - { - error_stream.Printf("Need object pointer but don't know the language\n"); - return false; - } - - Error object_ptr_error; - - object_ptr = GetObjectPointer(frame, object_name, object_ptr_error); - - if (!object_ptr_error.Success()) - { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); - object_ptr = 0; - } - - if (m_in_objectivec_method) - { - ConstString cmd_name("_cmd"); - - cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error); - - if (!object_ptr_error.Success()) - { - error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); - cmd_ptr = 0; - } - } - } - - if (m_materialized_address == LLDB_INVALID_ADDRESS) - { - Error alloc_error; - - IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; - - m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), - m_materializer_ap->GetStructAlignment(), - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - policy, - alloc_error); - - if (!alloc_error.Success()) - { - error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); - return false; - } - } - - struct_address = m_materialized_address; - - if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) - { - Error alloc_error; - - const size_t stack_frame_size = 512 * 1024; - - m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, - 8, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyHostOnly, - alloc_error); - - m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; - - if (!alloc_error.Success()) - { - error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); - return false; - } - } - - Error materialize_error; - - m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); - - if (!materialize_error.Success()) - { - error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); - return false; - } - } - return true; -} - -bool -ClangUserExpression::FinalizeJITExecution (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::ClangExpressionVariableSP &result, - lldb::addr_t function_stack_bottom, - lldb::addr_t function_stack_top) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --"); - - if (!m_dematerializer_sp) - { - error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present"); - return false; - } - - Error dematerialize_error; - - m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top); - - if (!dematerialize_error.Success()) - { - error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error")); - return false; - } - - if (result) - result->TransferAddress(); - - m_dematerializer_sp.reset(); - - return true; -} - -lldb::ExpressionResults -ClangUserExpression::Execute (Stream &error_stream, - ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - lldb::ClangUserExpressionSP &shared_ptr_to_me, - lldb::ClangExpressionVariableSP &result) -{ - // The expression log is quite verbose, and if you're just tracking the execution of the - // expression, it's quite convenient to have these logs come out with the STEP log as well. - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { - lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - - lldb::addr_t object_ptr = 0; - lldb::addr_t cmd_ptr = 0; - - if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) - { - error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); - return lldb::eExpressionSetupError; - } - - lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; - lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; - - if (m_can_interpret) - { - llvm::Module *module = m_execution_unit_sp->GetModule(); - llvm::Function *function = m_execution_unit_sp->GetFunction(); - - if (!module || !function) - { - error_stream.Printf("Supposed to interpret, but nothing is there"); - return lldb::eExpressionSetupError; - } - - Error interpreter_error; - - llvm::SmallVector args; - - if (m_needs_object_ptr) - { - args.push_back(object_ptr); - - if (m_in_objectivec_method) - args.push_back(cmd_ptr); - } - - args.push_back(struct_address); - - function_stack_bottom = m_stack_frame_bottom; - function_stack_top = m_stack_frame_top; - - IRInterpreter::Interpret (*module, - *function, - args, - *m_execution_unit_sp.get(), - interpreter_error, - function_stack_bottom, - function_stack_top, - exe_ctx); - - if (!interpreter_error.Success()) - { - error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); - return lldb::eExpressionDiscarded; - } - } - else - { - if (!exe_ctx.HasThreadScope()) - { - error_stream.Printf("ClangUserExpression::Execute called with no thread selected."); - return lldb::eExpressionSetupError; - } - - Address wrapper_address (m_jit_start_addr); - - llvm::SmallVector args; - - if (m_needs_object_ptr) { - args.push_back(object_ptr); - if (m_in_objectivec_method) - args.push_back(cmd_ptr); - } - - args.push_back(struct_address); - - lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), - wrapper_address, - args, - options, - shared_ptr_to_me)); - - if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) - return lldb::eExpressionSetupError; - - ThreadPlanCallUserExpression *user_expression_plan = static_cast(call_plan_sp.get()); - - lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); - - function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); - function_stack_top = function_stack_pointer; - - if (log) - log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_stream); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - if (log) - log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); - - if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) - { - const char *error_desc = NULL; - - if (call_plan_sp) - { - lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); - if (real_stop_info_sp) - error_desc = real_stop_info_sp->GetDescription(); - } - if (error_desc) - error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); - else - error_stream.PutCString ("Execution was interrupted."); - - if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) - || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) - error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation."); - else - { - if (execution_result == lldb::eExpressionHitBreakpoint) - user_expression_plan->TransferExpressionOwnership(); - error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, " - "use \"thread return -x\" to return to the state before expression evaluation."); - } - - return execution_result; - } - else if (execution_result == lldb::eExpressionStoppedForDebug) - { - error_stream.PutCString ("Execution was halted at the first instruction of the expression " - "function because \"debug\" was requested.\n" - "Use \"thread return -x\" to return to the state before expression evaluation."); - return execution_result; - } - else if (execution_result != lldb::eExpressionCompleted) - { - error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); - return execution_result; - } - } - - if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) - { - return lldb::eExpressionCompleted; - } - else - { - return lldb::eExpressionResultUnavailable; - } - } - else - { - error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); - return lldb::eExpressionSetupError; - } -} - -lldb::ExpressionResults -ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); - const lldb::LanguageType language = options.GetLanguage(); - const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; - lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == NULL || process->GetState() != lldb::eStateStopped) - { - if (execution_policy == eExecutionPolicyAlways) - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - - error.SetErrorString ("expression needed to run but couldn't"); - - return execution_results; - } - } - - if (process == NULL || !process->CanJIT()) - execution_policy = eExecutionPolicyNever; - - const char *full_prefix = NULL; - const char *option_prefix = options.GetPrefix(); - std::string full_prefix_storage; - if (expr_prefix && option_prefix) - { - full_prefix_storage.assign(expr_prefix); - full_prefix_storage.append(option_prefix); - if (!full_prefix_storage.empty()) - full_prefix = full_prefix_storage.c_str(); - } - else if (expr_prefix) - full_prefix = expr_prefix; - else - full_prefix = option_prefix; - - lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type)); - - StreamString error_stream; - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); - - const bool keep_expression_in_memory = true; - const bool generate_debug_info = options.GetGenerateDebugInfo(); - - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) - { - error.SetErrorString ("expression interrupted by callback before parse"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - return lldb::eExpressionInterrupted; - } - - if (!user_expression_sp->Parse (error_stream, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info)) - { - execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); - } - else - { - lldb::ClangExpressionVariableSP expr_result; - - if (execution_policy == eExecutionPolicyNever && - !user_expression_sp->CanInterpret()) - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - - if (error_stream.GetString().empty()) - error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); - } - else - { - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - return lldb::eExpressionInterrupted; - } - - error_stream.GetString().clear(); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); - - execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - options, - user_expression_sp, - expr_result); - - if (options.GetResultIsInternal() && expr_result && process) - { - process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); - } - - if (execution_results != lldb::eExpressionCompleted) - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); - - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); - } - else - { - if (expr_result) - { - result_valobj_sp = expr_result->GetValueObject(); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", - result_valobj_sp->GetValueAsCString()); - } - else - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); - - error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); - } - } - } - } - - if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); - return lldb::eExpressionInterrupted; - } - - if (result_valobj_sp.get() == NULL) - { - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - } - - return execution_results; -} diff --git a/source/Expression/ClangUtilityFunction.cpp b/source/Expression/ClangUtilityFunction.cpp deleted file mode 100644 index de5b0c1b03f4..000000000000 --- a/source/Expression/ClangUtilityFunction.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//===-- ClangUserExpression.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 -#if HAVE_SYS_TYPES_H -# include -#endif - -// C++ Includes - -#include "lldb/Core/ConstString.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangUtilityFunction.h" -#include "lldb/Expression/ExpressionSourceCode.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Target.h" - -using namespace lldb_private; - -//------------------------------------------------------------------ -/// Constructor -/// -/// @param[in] text -/// The text of the function. Must be a full translation unit. -/// -/// @param[in] name -/// The name of the function, as used in the text. -//------------------------------------------------------------------ -ClangUtilityFunction::ClangUtilityFunction (const char *text, - const char *name) : - ClangExpression (), - m_expr_decl_map (), - m_execution_unit_sp (), - m_jit_module_wp (), - m_function_text (ExpressionSourceCode::g_expression_prefix), - m_function_name (name) -{ - if (text && text[0]) - m_function_text.append (text); -} - -ClangUtilityFunction::~ClangUtilityFunction () -{ - lldb::ProcessSP process_sp (m_jit_process_wp.lock()); - if (process_sp) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } - -} - -//------------------------------------------------------------------ -/// Install the utility function into a process -/// -/// @param[in] error_stream -/// A stream to print parse errors and warnings to. -/// -/// @param[in] exe_ctx -/// The execution context to install the utility function to. -/// -/// @return -/// True on success (no errors); false otherwise. -//------------------------------------------------------------------ -bool -ClangUtilityFunction::Install (Stream &error_stream, - ExecutionContext &exe_ctx) -{ - if (m_jit_start_addr != LLDB_INVALID_ADDRESS) - { - error_stream.PutCString("error: already installed\n"); - return false; - } - - //////////////////////////////////// - // Set up the target and compiler - // - - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - { - error_stream.PutCString ("error: invalid target\n"); - return false; - } - - Process *process = exe_ctx.GetProcessPtr(); - - if (!process) - { - error_stream.PutCString ("error: invalid process\n"); - return false; - } - - ////////////////////////// - // Parse the expression - // - - bool keep_result_in_memory = false; - - m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); - - if (!m_expr_decl_map->WillParse(exe_ctx, NULL)) - { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); - return false; - } - - const bool generate_debug_info = true; - ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); - - unsigned num_errors = parser.Parse (error_stream); - - if (num_errors) - { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - - m_expr_decl_map.reset(); - - return false; - } - - ////////////////////////////////// - // JIT the output of the parser - // - - bool can_interpret = false; // should stay that way - - Error jit_error = parser.PrepareForExecution (m_jit_start_addr, - m_jit_end_addr, - m_execution_unit_sp, - exe_ctx, - can_interpret, - eExecutionPolicyAlways); - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS) - { - m_jit_process_wp = process->shared_from_this(); - if (parser.GetGenerateDebugInfo()) - { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); - - if (jit_module_sp) - { - ConstString const_func_name(FunctionName()); - FileSpec jit_file; - jit_file.GetFilename() = const_func_name; - jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); - m_jit_module_wp = jit_module_sp; - target->GetImages().Append(jit_module_sp); - } - } - } - -#if 0 - // jingham: look here - StreamFile logfile ("/tmp/exprs.txt", "a"); - logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", - m_jit_start_addr, - m_function_name.c_str(), - m_function_text.c_str()); -#endif - - m_expr_decl_map->DidParse(); - - m_expr_decl_map.reset(); - - if (jit_error.Success()) - { - return true; - } - else - { - const char *error_cstr = jit_error.AsCString(); - if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); - else - error_stream.Printf ("error: expression can't be interpreted or run\n"); - return false; - } -} - - diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp index 9307c84510b0..ebcc28460395 100644 --- a/source/Expression/DWARFExpression.cpp +++ b/source/Expression/DWARFExpression.cpp @@ -24,8 +24,8 @@ #include "lldb/Core/Value.h" #include "lldb/Core/VMRange.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangExpressionVariable.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h" +#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" @@ -38,190 +38,27 @@ #include "lldb/Target/StackID.h" #include "lldb/Target/Thread.h" +#include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h" + using namespace lldb; using namespace lldb_private; -// TODO- why is this also defined (in a better way) in DWARFDefines.cpp? -const char * -DW_OP_value_to_name (uint32_t val) +static lldb::addr_t +ReadAddressFromDebugAddrSection(const DWARFCompileUnit* dwarf_cu, uint32_t index) { - static char invalid[100]; - switch (val) { - case 0x03: return "DW_OP_addr"; - case 0x06: return "DW_OP_deref"; - case 0x08: return "DW_OP_const1u"; - case 0x09: return "DW_OP_const1s"; - case 0x0a: return "DW_OP_const2u"; - case 0x0b: return "DW_OP_const2s"; - case 0x0c: return "DW_OP_const4u"; - case 0x0d: return "DW_OP_const4s"; - case 0x0e: return "DW_OP_const8u"; - case 0x0f: return "DW_OP_const8s"; - case 0x10: return "DW_OP_constu"; - case 0x11: return "DW_OP_consts"; - case 0x12: return "DW_OP_dup"; - case 0x13: return "DW_OP_drop"; - case 0x14: return "DW_OP_over"; - case 0x15: return "DW_OP_pick"; - case 0x16: return "DW_OP_swap"; - case 0x17: return "DW_OP_rot"; - case 0x18: return "DW_OP_xderef"; - case 0x19: return "DW_OP_abs"; - case 0x1a: return "DW_OP_and"; - case 0x1b: return "DW_OP_div"; - case 0x1c: return "DW_OP_minus"; - case 0x1d: return "DW_OP_mod"; - case 0x1e: return "DW_OP_mul"; - case 0x1f: return "DW_OP_neg"; - case 0x20: return "DW_OP_not"; - case 0x21: return "DW_OP_or"; - case 0x22: return "DW_OP_plus"; - case 0x23: return "DW_OP_plus_uconst"; - case 0x24: return "DW_OP_shl"; - case 0x25: return "DW_OP_shr"; - case 0x26: return "DW_OP_shra"; - case 0x27: return "DW_OP_xor"; - case 0x2f: return "DW_OP_skip"; - case 0x28: return "DW_OP_bra"; - case 0x29: return "DW_OP_eq"; - case 0x2a: return "DW_OP_ge"; - case 0x2b: return "DW_OP_gt"; - case 0x2c: return "DW_OP_le"; - case 0x2d: return "DW_OP_lt"; - case 0x2e: return "DW_OP_ne"; - case 0x30: return "DW_OP_lit0"; - case 0x31: return "DW_OP_lit1"; - case 0x32: return "DW_OP_lit2"; - case 0x33: return "DW_OP_lit3"; - case 0x34: return "DW_OP_lit4"; - case 0x35: return "DW_OP_lit5"; - case 0x36: return "DW_OP_lit6"; - case 0x37: return "DW_OP_lit7"; - case 0x38: return "DW_OP_lit8"; - case 0x39: return "DW_OP_lit9"; - case 0x3a: return "DW_OP_lit10"; - case 0x3b: return "DW_OP_lit11"; - case 0x3c: return "DW_OP_lit12"; - case 0x3d: return "DW_OP_lit13"; - case 0x3e: return "DW_OP_lit14"; - case 0x3f: return "DW_OP_lit15"; - case 0x40: return "DW_OP_lit16"; - case 0x41: return "DW_OP_lit17"; - case 0x42: return "DW_OP_lit18"; - case 0x43: return "DW_OP_lit19"; - case 0x44: return "DW_OP_lit20"; - case 0x45: return "DW_OP_lit21"; - case 0x46: return "DW_OP_lit22"; - case 0x47: return "DW_OP_lit23"; - case 0x48: return "DW_OP_lit24"; - case 0x49: return "DW_OP_lit25"; - case 0x4a: return "DW_OP_lit26"; - case 0x4b: return "DW_OP_lit27"; - case 0x4c: return "DW_OP_lit28"; - case 0x4d: return "DW_OP_lit29"; - case 0x4e: return "DW_OP_lit30"; - case 0x4f: return "DW_OP_lit31"; - case 0x50: return "DW_OP_reg0"; - case 0x51: return "DW_OP_reg1"; - case 0x52: return "DW_OP_reg2"; - case 0x53: return "DW_OP_reg3"; - case 0x54: return "DW_OP_reg4"; - case 0x55: return "DW_OP_reg5"; - case 0x56: return "DW_OP_reg6"; - case 0x57: return "DW_OP_reg7"; - case 0x58: return "DW_OP_reg8"; - case 0x59: return "DW_OP_reg9"; - case 0x5a: return "DW_OP_reg10"; - case 0x5b: return "DW_OP_reg11"; - case 0x5c: return "DW_OP_reg12"; - case 0x5d: return "DW_OP_reg13"; - case 0x5e: return "DW_OP_reg14"; - case 0x5f: return "DW_OP_reg15"; - case 0x60: return "DW_OP_reg16"; - case 0x61: return "DW_OP_reg17"; - case 0x62: return "DW_OP_reg18"; - case 0x63: return "DW_OP_reg19"; - case 0x64: return "DW_OP_reg20"; - case 0x65: return "DW_OP_reg21"; - case 0x66: return "DW_OP_reg22"; - case 0x67: return "DW_OP_reg23"; - case 0x68: return "DW_OP_reg24"; - case 0x69: return "DW_OP_reg25"; - case 0x6a: return "DW_OP_reg26"; - case 0x6b: return "DW_OP_reg27"; - case 0x6c: return "DW_OP_reg28"; - case 0x6d: return "DW_OP_reg29"; - case 0x6e: return "DW_OP_reg30"; - case 0x6f: return "DW_OP_reg31"; - case 0x70: return "DW_OP_breg0"; - case 0x71: return "DW_OP_breg1"; - case 0x72: return "DW_OP_breg2"; - case 0x73: return "DW_OP_breg3"; - case 0x74: return "DW_OP_breg4"; - case 0x75: return "DW_OP_breg5"; - case 0x76: return "DW_OP_breg6"; - case 0x77: return "DW_OP_breg7"; - case 0x78: return "DW_OP_breg8"; - case 0x79: return "DW_OP_breg9"; - case 0x7a: return "DW_OP_breg10"; - case 0x7b: return "DW_OP_breg11"; - case 0x7c: return "DW_OP_breg12"; - case 0x7d: return "DW_OP_breg13"; - case 0x7e: return "DW_OP_breg14"; - case 0x7f: return "DW_OP_breg15"; - case 0x80: return "DW_OP_breg16"; - case 0x81: return "DW_OP_breg17"; - case 0x82: return "DW_OP_breg18"; - case 0x83: return "DW_OP_breg19"; - case 0x84: return "DW_OP_breg20"; - case 0x85: return "DW_OP_breg21"; - case 0x86: return "DW_OP_breg22"; - case 0x87: return "DW_OP_breg23"; - case 0x88: return "DW_OP_breg24"; - case 0x89: return "DW_OP_breg25"; - case 0x8a: return "DW_OP_breg26"; - case 0x8b: return "DW_OP_breg27"; - case 0x8c: return "DW_OP_breg28"; - case 0x8d: return "DW_OP_breg29"; - case 0x8e: return "DW_OP_breg30"; - case 0x8f: return "DW_OP_breg31"; - case 0x90: return "DW_OP_regx"; - case 0x91: return "DW_OP_fbreg"; - case 0x92: return "DW_OP_bregx"; - case 0x93: return "DW_OP_piece"; - case 0x94: return "DW_OP_deref_size"; - case 0x95: return "DW_OP_xderef_size"; - case 0x96: return "DW_OP_nop"; - case 0x97: return "DW_OP_push_object_address"; - case 0x98: return "DW_OP_call2"; - case 0x99: return "DW_OP_call4"; - case 0x9a: return "DW_OP_call_ref"; -// case DW_OP_APPLE_array_ref: return "DW_OP_APPLE_array_ref"; -// case DW_OP_APPLE_extern: return "DW_OP_APPLE_extern"; - case DW_OP_APPLE_uninit: return "DW_OP_APPLE_uninit"; -// case DW_OP_APPLE_assign: return "DW_OP_APPLE_assign"; -// case DW_OP_APPLE_address_of: return "DW_OP_APPLE_address_of"; -// case DW_OP_APPLE_value_of: return "DW_OP_APPLE_value_of"; -// case DW_OP_APPLE_deref_type: return "DW_OP_APPLE_deref_type"; -// case DW_OP_APPLE_expr_local: return "DW_OP_APPLE_expr_local"; -// case DW_OP_APPLE_constf: return "DW_OP_APPLE_constf"; -// case DW_OP_APPLE_scalar_cast: return "DW_OP_APPLE_scalar_cast"; -// case DW_OP_APPLE_clang_cast: return "DW_OP_APPLE_clang_cast"; -// case DW_OP_APPLE_clear: return "DW_OP_APPLE_clear"; -// case DW_OP_APPLE_error: return "DW_OP_APPLE_error"; - default: - snprintf (invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val); - return invalid; - } + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + return dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size); } - //---------------------------------------------------------------------- // DWARFExpression constructor //---------------------------------------------------------------------- -DWARFExpression::DWARFExpression() : +DWARFExpression::DWARFExpression(DWARFCompileUnit* dwarf_cu) : m_module_wp(), m_data(), + m_dwarf_cu(dwarf_cu), m_reg_kind (eRegisterKindDWARF), m_loclist_slide (LLDB_INVALID_ADDRESS) { @@ -230,15 +67,21 @@ DWARFExpression::DWARFExpression() : DWARFExpression::DWARFExpression(const DWARFExpression& rhs) : m_module_wp(rhs.m_module_wp), m_data(rhs.m_data), + m_dwarf_cu(rhs.m_dwarf_cu), m_reg_kind (rhs.m_reg_kind), m_loclist_slide(rhs.m_loclist_slide) { } -DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length) : +DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp, + const DataExtractor& data, + DWARFCompileUnit* dwarf_cu, + lldb::offset_t data_offset, + lldb::offset_t data_length) : m_module_wp(), m_data(data, data_offset, data_length), + m_dwarf_cu(dwarf_cu), m_reg_kind (eRegisterKindDWARF), m_loclist_slide(LLDB_INVALID_ADDRESS) { @@ -624,6 +467,12 @@ DWARFExpression::DumpLocation (Stream *s, lldb::offset_t offset, lldb::offset_t case DW_OP_form_tls_address: s->PutCString("DW_OP_form_tls_address"); // 0x9b break; + case DW_OP_GNU_addr_index: // 0xfb + s->Printf("DW_OP_GNU_addr_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); + break; + case DW_OP_GNU_const_index: // 0xfc + s->Printf("DW_OP_GNU_const_index(0x%" PRIx64 ")", m_data.GetULEB128(&offset)); + break; case DW_OP_GNU_push_tls_address: s->PutCString("DW_OP_GNU_push_tls_address"); // 0xe0 break; @@ -709,8 +558,14 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t addr_t curr_base_addr = location_list_base_addr; while (m_data.ValidOffset(offset)) { - lldb::addr_t begin_addr_offset = m_data.GetAddress(&offset); - lldb::addr_t end_addr_offset = m_data.GetAddress(&offset); + addr_t begin_addr_offset = LLDB_INVALID_ADDRESS; + addr_t end_addr_offset = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, begin_addr_offset, end_addr_offset)) + break; + + if (begin_addr_offset == 0 && end_addr_offset == 0) + break; + if (begin_addr_offset < end_addr_offset) { if (count > 0) @@ -723,11 +578,6 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t s->PutChar('}'); offset += location_length; } - else if (begin_addr_offset == 0 && end_addr_offset == 0) - { - // The end of the location list is marked by both the start and end offset being zero - break; - } else { if ((m_data.GetAddressByteSize() == 4 && (begin_addr_offset == UINT32_MAX)) || @@ -1027,8 +877,10 @@ GetOpcodeDataSize (const DataExtractor &data, const lldb::offset_t data_offset, case DW_OP_regx: // 0x90 1 ULEB128 register case DW_OP_fbreg: // 0x91 1 SLEB128 offset case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed + case DW_OP_GNU_addr_index: // 0xfb 1 ULEB128 index + case DW_OP_GNU_const_index: // 0xfc 1 ULEB128 index data.Skip_LEB128(&offset); - return offset - data_offset; + return offset - data_offset; // All opcodes that have a 2 ULEB (signed or unsigned) arguments case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset @@ -1070,6 +922,22 @@ DWARFExpression::GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) cons else ++curr_op_addr_idx; } + else if (op == DW_OP_GNU_addr_index) + { + uint64_t index = m_data.GetULEB128(&offset); + if (curr_op_addr_idx == op_addr_idx) + { + if (!m_dwarf_cu) + { + error = true; + break; + } + + return ReadAddressFromDebugAddrSection(m_dwarf_cu, index); + } + else + ++curr_op_addr_idx; + } else { const offset_t op_arg_size = GetOpcodeDataSize (m_data, offset, op); @@ -1104,7 +972,7 @@ DWARFExpression::Update_DW_OP_addr (lldb::addr_t file_addr) // So first we copy the data into a heap buffer std::unique_ptr head_data_ap (new DataBufferHeap (m_data.GetDataStart(), - m_data.GetByteSize())); + m_data.GetByteSize())); // Make en encoder so we can write the address into the buffer using // the correct byte order (endianness) @@ -1150,20 +1018,21 @@ DWARFExpression::LocationListContainsAddress (lldb::addr_t loclist_base_addr, ll while (m_data.ValidOffset(offset)) { // We need to figure out what the value is for the location. - addr_t lo_pc = m_data.GetAddress(&offset); - addr_t hi_pc = m_data.GetAddress(&offset); + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) + break; + if (lo_pc == 0 && hi_pc == 0) break; - else - { - lo_pc += loclist_base_addr - m_loclist_slide; - hi_pc += loclist_base_addr - m_loclist_slide; - if (lo_pc <= addr && addr < hi_pc) - return true; + lo_pc += loclist_base_addr - m_loclist_slide; + hi_pc += loclist_base_addr - m_loclist_slide; - offset += m_data.GetU16(&offset); - } + if (lo_pc <= addr && addr < hi_pc) + return true; + + offset += m_data.GetU16(&offset); } } return false; @@ -1186,24 +1055,23 @@ DWARFExpression::GetLocation (addr_t base_addr, addr_t pc, lldb::offset_t &offse while (m_data.ValidOffset(offset)) { // We need to figure out what the value is for the location. - addr_t lo_pc = m_data.GetAddress(&offset); - addr_t hi_pc = m_data.GetAddress(&offset); + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) + break; + if (lo_pc == 0 && hi_pc == 0) - { break; - } - else - { - lo_pc += curr_base_addr - m_loclist_slide; - hi_pc += curr_base_addr - m_loclist_slide; - - length = m_data.GetU16(&offset); - - if (length > 0 && lo_pc <= pc && pc < hi_pc) - return true; - offset += length; - } + lo_pc += curr_base_addr - m_loclist_slide; + hi_pc += curr_base_addr - m_loclist_slide; + + length = m_data.GetU16(&offset); + + if (length > 0 && lo_pc <= pc && pc < hi_pc) + return true; + + offset += length; } } offset = LLDB_INVALID_OFFSET; @@ -1295,25 +1163,36 @@ DWARFExpression::Evaluate while (m_data.ValidOffset(offset)) { // We need to figure out what the value is for the location. - addr_t lo_pc = m_data.GetAddress(&offset); - addr_t hi_pc = m_data.GetAddress(&offset); + addr_t lo_pc = LLDB_INVALID_ADDRESS; + addr_t hi_pc = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(m_dwarf_cu, m_data, &offset, lo_pc, hi_pc)) + break; + if (lo_pc == 0 && hi_pc == 0) - { break; - } - else - { - lo_pc += curr_loclist_base_load_addr - m_loclist_slide; - hi_pc += curr_loclist_base_load_addr - m_loclist_slide; - uint16_t length = m_data.GetU16(&offset); + lo_pc += curr_loclist_base_load_addr - m_loclist_slide; + hi_pc += curr_loclist_base_load_addr - m_loclist_slide; - if (length > 0 && lo_pc <= pc && pc < hi_pc) - { - return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr); - } - offset += length; + uint16_t length = m_data.GetU16(&offset); + + if (length > 0 && lo_pc <= pc && pc < hi_pc) + { + return DWARFExpression::Evaluate (exe_ctx, + expr_locals, + decl_map, + reg_ctx, + module_sp, + m_data, + m_dwarf_cu, + offset, + length, + m_reg_kind, + initial_value_ptr, + result, + error_ptr); } + offset += length; } } if (error_ptr) @@ -1322,7 +1201,19 @@ DWARFExpression::Evaluate } // Not a location list, just a single expression. - return DWARFExpression::Evaluate (exe_ctx, expr_locals, decl_map, reg_ctx, module_sp, m_data, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr); + return DWARFExpression::Evaluate (exe_ctx, + expr_locals, + decl_map, + reg_ctx, + module_sp, + m_data, + m_dwarf_cu, + 0, + m_data.GetByteSize(), + m_reg_kind, + initial_value_ptr, + result, + error_ptr); } @@ -1336,6 +1227,7 @@ DWARFExpression::Evaluate RegisterContext *reg_ctx, lldb::ModuleSP module_sp, const DataExtractor& opcodes, + DWARFCompileUnit* dwarf_cu, const lldb::offset_t opcodes_offset, const lldb::offset_t opcodes_length, const lldb::RegisterKind reg_kind, @@ -2711,7 +2603,7 @@ DWARFExpression::Evaluate return false; } } - else if (!stack.empty()) + else { // If this is the second or later piece there should be a value on the stack if (pieces.GetBuffer().GetByteSize() != op_piece_offset) @@ -2950,6 +2842,69 @@ DWARFExpression::Evaluate } break; + //---------------------------------------------------------------------- + // OPCODE: DW_OP_GNU_addr_index + // OPERANDS: 1 + // ULEB128: index to the .debug_addr section + // DESCRIPTION: Pushes an address to the stack from the .debug_addr + // section with the base address specified by the DW_AT_addr_base + // attribute and the 0 based index is the ULEB128 encoded index. + //---------------------------------------------------------------------- + case DW_OP_GNU_addr_index: + { + if (!dwarf_cu) + { + if (error_ptr) + error_ptr->SetErrorString ("DW_OP_GNU_addr_index found without a compile unit being specified"); + return false; + } + uint64_t index = opcodes.GetULEB128(&offset); + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + uint64_t value = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset, index_size); + stack.push_back(Scalar(value)); + stack.back().SetValueType(Value::eValueTypeFileAddress); + } + break; + + //---------------------------------------------------------------------- + // OPCODE: DW_OP_GNU_const_index + // OPERANDS: 1 + // ULEB128: index to the .debug_addr section + // DESCRIPTION: Pushes an constant with the size of a machine address to + // the stack from the .debug_addr section with the base address specified + // by the DW_AT_addr_base attribute and the 0 based index is the ULEB128 + // encoded index. + //---------------------------------------------------------------------- + case DW_OP_GNU_const_index: + { + if (!dwarf_cu) + { + if (error_ptr) + error_ptr->SetErrorString ("DW_OP_GNU_const_index found without a compile unit being specified"); + return false; + } + uint64_t index = opcodes.GetULEB128(&offset); + uint32_t index_size = dwarf_cu->GetAddressByteSize(); + dw_offset_t addr_base = dwarf_cu->GetAddrBase(); + lldb::offset_t offset = addr_base + index * index_size; + const DWARFDataExtractor& debug_addr = dwarf_cu->GetSymbolFileDWARF()->get_debug_addr_data(); + switch (index_size) + { + case 4: + stack.push_back(Scalar(debug_addr.GetU32(&offset))); + break; + case 8: + stack.push_back(Scalar(debug_addr.GetU64(&offset))); + break; + default: + assert(false && "Unhandled index size"); + return false; + } + } + break; + default: if (log) log->Printf("Unhandled opcode %s in DWARFExpression.", DW_OP_value_to_name(op)); @@ -2990,3 +2945,255 @@ DWARFExpression::Evaluate return true; // Return true on success } +size_t +DWARFExpression::LocationListSize(const DWARFCompileUnit* dwarf_cu, + const DataExtractor& debug_loc_data, + lldb::offset_t offset) +{ + const lldb::offset_t debug_loc_offset = offset; + while (debug_loc_data.ValidOffset(offset)) + { + lldb::addr_t start_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t end_addr = LLDB_INVALID_ADDRESS; + if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, start_addr, end_addr)) + break; + + if (start_addr == 0 && end_addr == 0) + break; + + uint16_t loc_length = debug_loc_data.GetU16(&offset); + offset += loc_length; + } + + if (offset > debug_loc_offset) + return offset - debug_loc_offset; + return 0; +} + +bool +DWARFExpression::AddressRangeForLocationListEntry(const DWARFCompileUnit* dwarf_cu, + const DataExtractor& debug_loc_data, + lldb::offset_t* offset_ptr, + lldb::addr_t& low_pc, + lldb::addr_t& high_pc) +{ + if (!debug_loc_data.ValidOffset(*offset_ptr)) + return false; + + switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat()) + { + case NonLocationList: + return false; + case RegularLocationList: + low_pc = debug_loc_data.GetAddress(offset_ptr); + high_pc = debug_loc_data.GetAddress(offset_ptr); + return true; + case SplitDwarfLocationList: + switch (debug_loc_data.GetU8(offset_ptr)) + { + case DW_LLE_end_of_list_entry: + return false; + case DW_LLE_start_end_entry: + { + uint64_t index = debug_loc_data.GetULEB128(offset_ptr); + low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + index = debug_loc_data.GetULEB128(offset_ptr); + high_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + return true; + } + case DW_LLE_start_length_entry: + { + uint64_t index = debug_loc_data.GetULEB128(offset_ptr); + low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index); + uint32_t length = debug_loc_data.GetU32(offset_ptr); + high_pc = low_pc + length; + return true; + } + default: + // Not supported entry type + return false; + } + } + assert (false && "Not supported location list type"); + return false; +} + +static bool +print_dwarf_exp_op (Stream &s, + const DataExtractor& data, + lldb::offset_t *offset_ptr, + int address_size, + int dwarf_ref_size) +{ + uint8_t opcode = data.GetU8(offset_ptr); + DRC_class opcode_class; + uint64_t uint; + int64_t sint; + + int size; + + opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); + + s.Printf("%s ", DW_OP_value_to_name (opcode)); + + /* Does this take zero parameters? If so we can shortcut this function. */ + if (opcode_class == DRC_ZEROOPERANDS) + return true; + + if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) + { + uint = data.GetULEB128(offset_ptr); + sint = data.GetSLEB128(offset_ptr); + s.Printf("%" PRIu64 " %" PRIi64, uint, sint); + return true; + } + if (opcode_class != DRC_ONEOPERAND) + { + s.Printf("UNKNOWN OP %u", opcode); + return false; + } + + switch (opcode) + { + case DW_OP_addr: size = address_size; break; + case DW_OP_const1u: size = 1; break; + case DW_OP_const1s: size = -1; break; + case DW_OP_const2u: size = 2; break; + case DW_OP_const2s: size = -2; break; + case DW_OP_const4u: size = 4; break; + case DW_OP_const4s: size = -4; break; + case DW_OP_const8u: size = 8; break; + case DW_OP_const8s: size = -8; break; + case DW_OP_constu: size = 128; break; + case DW_OP_consts: size = -128; break; + case DW_OP_fbreg: size = -128; break; + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + size = -128; break; + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + size = 1; break; + case DW_OP_skip: + case DW_OP_bra: + size = -2; break; + case DW_OP_call2: + size = 2; break; + case DW_OP_call4: + size = 4; break; + case DW_OP_call_ref: + size = dwarf_ref_size; break; + case DW_OP_piece: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_GNU_addr_index: + case DW_OP_GNU_const_index: + size = 128; break; + default: + s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); + return true; + } + + switch (size) + { + case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break; + case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break; + case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break; + case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break; + case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break; + case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break; + case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break; + case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break; + case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break; + case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break; + } + + return false; +} + +bool +DWARFExpression::PrintDWARFExpression(Stream &s, + const DataExtractor& data, + int address_size, + int dwarf_ref_size, + bool location_expression) +{ + int op_count = 0; + lldb::offset_t offset = 0; + while (data.ValidOffset(offset)) + { + if (location_expression && op_count > 0) + return false; + if (op_count > 0) + s.PutCString(", "); + if (!print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size)) + return false; + op_count++; + } + + return true; +} + +void +DWARFExpression::PrintDWARFLocationList(Stream &s, + const DWARFCompileUnit* cu, + const DataExtractor& debug_loc_data, + lldb::offset_t offset) +{ + uint64_t start_addr, end_addr; + uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); + s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu)); + dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; + while (debug_loc_data.ValidOffset(offset)) + { + start_addr = debug_loc_data.GetMaxU64(&offset,addr_size); + end_addr = debug_loc_data.GetMaxU64(&offset,addr_size); + + if (start_addr == 0 && end_addr == 0) + break; + + s.PutCString("\n "); + s.Indent(); + if (cu) + s.AddressRange (start_addr + base_addr, + end_addr + base_addr, + cu->GetAddressByteSize(), + NULL, + ": "); + uint32_t loc_length = debug_loc_data.GetU16(&offset); + + DataExtractor locationData(debug_loc_data, offset, loc_length); + PrintDWARFExpression (s, locationData, addr_size, 4, false); + offset += loc_length; + } +} diff --git a/source/Expression/Expression.cpp b/source/Expression/Expression.cpp new file mode 100644 index 000000000000..e5dd9c03db7d --- /dev/null +++ b/source/Expression/Expression.cpp @@ -0,0 +1,32 @@ +//===-- Expression.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/Expression.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +Expression::Expression (Target &target) : + m_target_wp (target.shared_from_this()), + m_jit_start_addr (LLDB_INVALID_ADDRESS), + m_jit_end_addr (LLDB_INVALID_ADDRESS) +{ + // Can't make any kind of expression without a target. + assert (m_target_wp.lock()); +} + +Expression::Expression (ExecutionContextScope &exe_scope) : + m_target_wp (exe_scope.CalculateTarget()), + m_jit_start_addr (LLDB_INVALID_ADDRESS), + m_jit_end_addr (LLDB_INVALID_ADDRESS) +{ + assert (m_target_wp.lock()); +} + diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp index 9a42510d0a24..c4ab7a95d7a9 100644 --- a/source/Expression/ExpressionSourceCode.cpp +++ b/source/Expression/ExpressionSourceCode.cpp @@ -10,9 +10,12 @@ #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/StackFrame.h" @@ -56,6 +59,121 @@ extern "C" } )"; +namespace { + +class AddMacroState +{ + enum State + { + CURRENT_FILE_NOT_YET_PUSHED, + CURRENT_FILE_PUSHED, + CURRENT_FILE_POPPED + }; + +public: + AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) + : m_state(CURRENT_FILE_NOT_YET_PUSHED), + m_current_file(current_file), + m_current_file_line(current_file_line) + { } + + void + StartFile(const FileSpec &file) + { + m_file_stack.push_back(file); + if (file == m_current_file) + m_state = CURRENT_FILE_PUSHED; + } + + void + EndFile() + { + if (m_file_stack.size() == 0) + return; + + FileSpec old_top = m_file_stack.back(); + m_file_stack.pop_back(); + if (old_top == m_current_file) + m_state = CURRENT_FILE_POPPED; + } + + // An entry is valid if it occurs before the current line in + // the current file. + bool + IsValidEntry(uint32_t line) + { + switch (m_state) + { + case CURRENT_FILE_NOT_YET_PUSHED: + return true; + case CURRENT_FILE_POPPED: + return false; + case CURRENT_FILE_PUSHED: + // If we are in file included in the current file, + // the entry should be added. + if (m_file_stack.back() != m_current_file) + return true; + + if (line >= m_current_file_line) + return false; + else + return true; + } + } + +private: + std::vector m_file_stack; + State m_state; + FileSpec m_current_file; + uint32_t m_current_file_line; +}; + +} // anonymous namespace + +static void +AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) +{ + if (dm == nullptr) + return; + + for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) + { + const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); + uint32_t line; + + switch (entry.GetType()) + { + case DebugMacroEntry::DEFINE: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::UNDEF: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::START_FILE: + line = entry.GetLineNumber(); + if (state.IsValidEntry(line)) + state.StartFile(entry.GetFileSpec(comp_unit)); + else + return; + break; + case DebugMacroEntry::END_FILE: + state.EndFile(); + break; + case DebugMacroEntry::INDIRECT: + AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); + break; + default: + // This is an unknown/invalid entry. Ignore. + break; + } + } +} bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const { @@ -82,7 +200,8 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) { - const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = target->GetPersistentVariables().GetHandLoadedClangModules(); + ClangPersistentVariables *persistent_vars = llvm::cast(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) @@ -118,6 +237,23 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi } } + + StreamString debug_macros_stream; + if (StackFrame *frame = exe_ctx.GetFramePtr()) + { + const SymbolContext &sc = frame->GetSymbolContext( + lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); + + if (sc.comp_unit && sc.line_entry.IsValid()) + { + DebugMacros *dm = sc.comp_unit->GetDebugMacros(); + if (dm) + { + AddMacroState state(sc.line_entry.file, sc.line_entry.line); + AddMacros(dm, sc.comp_unit, state, debug_macros_stream); + } + } + } if (m_wrap) { @@ -133,8 +269,9 @@ bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrappi StreamString wrap_stream; - wrap_stream.Printf("%s\n%s\n%s\n%s\n", + wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(), + debug_macros_stream.GetData(), g_expression_prefix, target_specific_defines, m_prefix.c_str()); diff --git a/source/Expression/ExpressionVariable.cpp b/source/Expression/ExpressionVariable.cpp new file mode 100644 index 000000000000..8bef60fdf1d7 --- /dev/null +++ b/source/Expression/ExpressionVariable.cpp @@ -0,0 +1,36 @@ +//===-- ExpressionVariable.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/Expression/ExpressionVariable.h" + +using namespace lldb_private; + +ExpressionVariable::~ExpressionVariable() +{ +} + +uint8_t * +ExpressionVariable::GetValueBytes() +{ + const size_t byte_size = m_frozen_sp->GetByteSize(); + if (byte_size > 0) + { + if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size) + { + m_frozen_sp->GetValue().ResizeData(byte_size); + m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor()); + } + return const_cast(m_frozen_sp->GetDataExtractor().GetDataStart()); + } + return NULL; +} + +PersistentExpressionState::~PersistentExpressionState () +{ +} diff --git a/source/Expression/FunctionCaller.cpp b/source/Expression/FunctionCaller.cpp new file mode 100644 index 000000000000..ddc378dcb416 --- /dev/null +++ b/source/Expression/FunctionCaller.cpp @@ -0,0 +1,406 @@ +//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +// Other libraries and framework includes + +// Project includes +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/State.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb_private; + +//---------------------------------------------------------------------- +// FunctionCaller constructor +//---------------------------------------------------------------------- +FunctionCaller::FunctionCaller +( + ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& functionAddress, + const ValueList &arg_value_list, + const char *name +) : + Expression (exe_scope), + m_execution_unit_sp(), + m_parser(), + m_jit_module_wp(), + m_name (name ? name : ""), + m_function_ptr (NULL), + m_function_addr (functionAddress), + m_function_return_type(return_type), + m_wrapper_function_name ("__lldb_caller_function"), + m_wrapper_struct_name ("__lldb_caller_struct"), + m_wrapper_args_addrs (), + m_arg_values (arg_value_list), + m_compiled (false), + m_JITted (false) +{ + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a FunctionCaller without a process. + assert (m_jit_process_wp.lock()); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +FunctionCaller::~FunctionCaller() +{ + lldb::ProcessSP process_sp (m_jit_process_wp.lock()); + if (process_sp) + { + lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); + if (jit_module_sp) + process_sp->GetTarget().GetImages().Remove(jit_module_sp); + } +} + +bool +FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) +{ + Process *process = exe_ctx.GetProcessPtr(); + + if (!process) + return false; + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + + if (!m_compiled) + return false; + + if (m_JITted) + return true; + + bool can_interpret = false; // should stay that way + + Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr, + m_jit_end_addr, + m_execution_unit_sp, + exe_ctx, + can_interpret, + eExecutionPolicyAlways)); + + if (!jit_error.Success()) + return false; + + if (m_parser->GetGenerateDebugInfo()) + { + lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) + { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + process->GetTarget().GetImages().Append(jit_module_sp); + } + } + if (process && m_jit_start_addr) + m_jit_process_wp = process->shared_from_this(); + + m_JITted = true; + + return true; +} + +bool +FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +{ + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors); +} + +// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. + +bool +FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + ValueList &arg_values, + Stream &errors) +{ + // All the information to reconstruct the struct is provided by the + // StructExtractor. + if (!m_struct_valid) + { + errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); + return false; + } + + Error error; + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == NULL) + return return_value; + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + + if (args_addr_ref == LLDB_INVALID_ADDRESS) + { + args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); + if (args_addr_ref == LLDB_INVALID_ADDRESS) + return false; + m_wrapper_args_addrs.push_back (args_addr_ref); + } + else + { + // Make sure this is an address that we've already handed out. + if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) + { + return false; + } + } + + // TODO: verify fun_addr needs to be a callable address + Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); + uint64_t first_offset = m_member_offsets[0]; + process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); + + // FIXME: We will need to extend this for Variadic functions. + + Error value_error; + + size_t num_args = arg_values.GetSize(); + if (num_args != m_arg_values.GetSize()) + { + errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); + return false; + } + + for (size_t i = 0; i < num_args; i++) + { + // FIXME: We should sanity check sizes. + + uint64_t offset = m_member_offsets[i+1]; // Clang sizes are in bytes. + Value *arg_value = arg_values.GetValueAtIndex(i); + + // FIXME: For now just do scalars: + + // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) + + if (arg_value->GetValueType() == Value::eValueTypeHostAddress && + arg_value->GetContextType() == Value::eContextTypeInvalid && + arg_value->GetCompilerType().IsPointerType()) + continue; + + const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); + + if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) + return false; + } + + return true; +} + +bool +FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +{ + if (CompileFunction(errors) != 0) + return false; + if (!WriteFunctionWrapper(exe_ctx, errors)) + return false; + if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors)) + return false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref); + + return true; +} + +lldb::ThreadPlanSP +FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, + lldb::addr_t args_addr, + const EvaluateExpressionOptions &options, + Stream &errors) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); + + // FIXME: Use the errors Stream for better error reporting. + Thread *thread = exe_ctx.GetThreadPtr(); + if (thread == NULL) + { + errors.Printf("Can't call a function without a valid thread."); + return NULL; + } + + // Okay, now run the function: + + Address wrapper_address (m_jit_start_addr); + + lldb::addr_t args = { args_addr }; + + lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread, + wrapper_address, + CompilerType(), + args, + options)); + new_plan_sp->SetIsMasterPlan(true); + new_plan_sp->SetOkayToDiscard (false); + return new_plan_sp; +} + +bool +FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) +{ + // Read the return value - it is the last field in the struct: + // FIXME: How does clang tell us there's no return value? We need to handle that case. + // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject + // to fetch the value. That way we can fetch any values we need. + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == NULL) + return false; + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + + if (process != jit_process_sp.get()) + return false; + + Error error; + ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error); + + if (error.Fail()) + return false; + + ret_value.SetCompilerType(m_function_return_type); + ret_value.SetValueType(Value::eValueTypeScalar); + return true; +} + +void +FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) +{ + std::list::iterator pos; + pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr); + if (pos != m_wrapper_args_addrs.end()) + m_wrapper_args_addrs.erase(pos); + + exe_ctx.GetProcessRef().DeallocateMemory(args_addr); +} + +lldb::ExpressionResults +FunctionCaller::ExecuteFunction( + ExecutionContext &exe_ctx, + lldb::addr_t *args_addr_ptr, + const EvaluateExpressionOptions &options, + Stream &errors, + Value &results) +{ + lldb::ExpressionResults return_value = lldb::eExpressionSetupError; + + // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore + // breakpoints, unwind on error, and don't try to debug it. + EvaluateExpressionOptions real_options = options; + real_options.SetDebug(false); + real_options.SetUnwindOnError(true); + real_options.SetIgnoreBreakpoints(true); + + lldb::addr_t args_addr; + + if (args_addr_ptr != NULL) + args_addr = *args_addr_ptr; + else + args_addr = LLDB_INVALID_ADDRESS; + + if (CompileFunction(errors) != 0) + return lldb::eExpressionSetupError; + + if (args_addr == LLDB_INVALID_ADDRESS) + { + if (!InsertFunction(exe_ctx, args_addr, errors)) + return lldb::eExpressionSetupError; + } + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + if (log) + log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); + + lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, + args_addr, + real_options, + errors); + if (!call_plan_sp) + return lldb::eExpressionSetupError; + + // We need to make sure we record the fact that we are running an expression here + // otherwise this fact will fail to be recorded when fetching an Objective-C object description + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, + call_plan_sp, + real_options, + errors); + + if (log) + { + if (return_value != lldb::eExpressionCompleted) + { + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); + } + else + { + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); + } + } + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + if (args_addr_ptr != NULL) + *args_addr_ptr = args_addr; + + if (return_value != lldb::eExpressionCompleted) + return return_value; + + FetchFunctionResults(exe_ctx, args_addr, results); + + if (args_addr_ptr == NULL) + DeallocateFunctionResults(exe_ctx, args_addr); + + return lldb::eExpressionCompleted; +} diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp index aa5d28bb8aad..30d7f6330f65 100644 --- a/source/Expression/IRDynamicChecks.cpp +++ b/source/Expression/IRDynamicChecks.cpp @@ -1,4 +1,4 @@ -//===-- IRDynamicChecks.cpp -------------------------------------------*- C++ -*-===// +//===-- IRDynamicChecks.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,23 +7,28 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" + +// Project includes #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" - -#include "llvm/Support/raw_ostream.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Value.h" +#include "lldb/Target/Target.h" using namespace llvm; using namespace lldb_private; @@ -40,20 +45,22 @@ static const char g_valid_pointer_check_text[] = " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n" "}"; -DynamicCheckerFunctions::DynamicCheckerFunctions () -{ -} +DynamicCheckerFunctions::DynamicCheckerFunctions() = default; -DynamicCheckerFunctions::~DynamicCheckerFunctions () -{ -} +DynamicCheckerFunctions::~DynamicCheckerFunctions() = default; bool DynamicCheckerFunctions::Install(Stream &error_stream, ExecutionContext &exe_ctx) { - m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text, - VALID_POINTER_CHECK_NAME)); + Error error; + m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, + lldb::eLanguageTypeC, + VALID_POINTER_CHECK_NAME, + error)); + if (error.Fail()) + return false; + if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) return false; @@ -80,12 +87,12 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa { // FIXME: We have to get the checkers to know why they scotched the call in more detail, // so we can print a better message here. - if (m_valid_pointer_check.get() != NULL && m_valid_pointer_check->ContainsAddress(addr)) + if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) { message.Printf ("Attempted to dereference an invalid pointer."); return true; } - else if (m_objc_object_check.get() != NULL && m_objc_object_check->ContainsAddress(addr)) + else if (m_objc_object_check && m_objc_object_check->ContainsAddress(addr)) { message.Printf ("Attempted to dereference an invalid ObjC Object or send it an unrecognized selector"); return true; @@ -93,7 +100,6 @@ DynamicCheckerFunctions::DoCheckersExplainStop (lldb::addr_t addr, Stream &messa return false; } - static std::string PrintValue(llvm::Value *V, bool truncate = false) { @@ -146,14 +152,12 @@ public: DynamicCheckerFunctions &checker_functions) : m_module(module), m_checker_functions(checker_functions), - m_i8ptr_ty(NULL), - m_intptr_ty(NULL) + m_i8ptr_ty(nullptr), + m_intptr_ty(nullptr) { } - virtual~Instrumenter () - { - } + virtual ~Instrumenter() = default; //------------------------------------------------------------------ /// Inspect a function to find instructions to instrument @@ -187,6 +191,7 @@ public: return true; } + protected: //------------------------------------------------------------------ /// Add instrumentation to a single instruction @@ -344,6 +349,7 @@ protected: InstVector m_to_instrument; ///< List of instructions the inspector found llvm::Module &m_module; ///< The module which is being instrumented DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process + private: PointerType *m_i8ptr_ty; IntegerType *m_intptr_ty; @@ -355,15 +361,14 @@ public: ValidPointerChecker (llvm::Module &module, DynamicCheckerFunctions &checker_functions) : Instrumenter(module, checker_functions), - m_valid_pointer_check_func(NULL) + m_valid_pointer_check_func(nullptr) { } - virtual ~ValidPointerChecker () - { - } -private: - bool InstrumentInstruction(llvm::Instruction *inst) + ~ValidPointerChecker() override = default; + +protected: + bool InstrumentInstruction(llvm::Instruction *inst) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -374,7 +379,7 @@ private: if (!m_valid_pointer_check_func) m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress()); - llvm::Value *dereferenced_ptr = NULL; + llvm::Value *dereferenced_ptr = nullptr; if (llvm::LoadInst *li = dyn_cast (inst)) dereferenced_ptr = li->getPointerOperand(); @@ -406,7 +411,7 @@ private: return true; } - bool InspectInstruction(llvm::Instruction &i) + bool InspectInstruction(llvm::Instruction &i) override { if (dyn_cast (&i) || dyn_cast (&i)) @@ -415,6 +420,7 @@ private: return true; } +private: llvm::Value *m_valid_pointer_check_func; }; @@ -424,14 +430,11 @@ public: ObjcObjectChecker(llvm::Module &module, DynamicCheckerFunctions &checker_functions) : Instrumenter(module, checker_functions), - m_objc_object_check_func(NULL) + m_objc_object_check_func(nullptr) { } - virtual - ~ObjcObjectChecker () - { - } + ~ObjcObjectChecker() override = default; enum msgSend_type { @@ -444,13 +447,13 @@ public: std::map msgSend_types; -private: - bool InstrumentInstruction(llvm::Instruction *inst) +protected: + bool InstrumentInstruction(llvm::Instruction *inst) override { CallInst *call_inst = dyn_cast(inst); if (!call_inst) - return false; // call_inst really shouldn't be NULL, because otherwise InspectInstruction wouldn't have registered it + return false; // call_inst really shouldn't be nullptr, because otherwise InspectInstruction wouldn't have registered it if (!m_objc_object_check_func) m_objc_object_check_func = BuildObjectCheckerFunc(m_checker_functions.m_objc_object_check->StartAddress()); @@ -504,7 +507,7 @@ private: return true; } - bool InspectInstruction(llvm::Instruction &i) + bool InspectInstruction(llvm::Instruction &i) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -593,6 +596,7 @@ private: return true; } +private: llvm::Value *m_objc_object_check_func; }; @@ -604,9 +608,7 @@ IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions, { } -IRDynamicChecks::~IRDynamicChecks() -{ -} +IRDynamicChecks::~IRDynamicChecks() = default; bool IRDynamicChecks::runOnModule(llvm::Module &M) @@ -623,7 +625,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M) return false; } - if (m_checker_functions.m_valid_pointer_check.get()) + if (m_checker_functions.m_valid_pointer_check) { ValidPointerChecker vpc(M, m_checker_functions); @@ -634,7 +636,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M) return false; } - if (m_checker_functions.m_objc_object_check.get()) + if (m_checker_functions.m_objc_object_check) { ObjcObjectChecker ooc(M, m_checker_functions); @@ -650,7 +652,7 @@ IRDynamicChecks::runOnModule(llvm::Module &M) std::string s; raw_string_ostream oss(s); - M.print(oss, NULL); + M.print(oss, nullptr); oss.flush(); diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp index 59c7fb6f786f..3f19c508c926 100644 --- a/source/Expression/IRExecutionUnit.cpp +++ b/source/Expression/IRExecutionUnit.cpp @@ -50,10 +50,12 @@ IRExecutionUnit::WriteNow (const uint8_t *bytes, size_t size, Error &error) { + const bool zero_memory = false; lldb::addr_t allocation_process_addr = Malloc (size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable, eAllocationPolicyMirror, + zero_memory, error); if (!error.Success()) @@ -432,6 +434,13 @@ IRExecutionUnit::GetRunnableInfo(Error &error, my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8); } } + else + { + record.dump(log); + + DataExtractor my_extractor ((const void*)record.m_host_address, record.m_size, lldb::eByteOrderBig, 8); + my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, DataExtractor::TypeUInt8); + } } } @@ -488,6 +497,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE sect_type = lldb::eSectionTypeDWARFDebugAbbrev; else if (dwarf_name.equals("aranges")) sect_type = lldb::eSectionTypeDWARFDebugAranges; + else if (dwarf_name.equals("addr")) + sect_type = lldb::eSectionTypeDWARFDebugAddr; break; case 'f': @@ -522,6 +533,8 @@ IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRE case 's': if (dwarf_name.equals("str")) sect_type = lldb::eSectionTypeDWARFDebugStr; + else if (dwarf_name.equals("str_offsets")) + sect_type = lldb::eSectionTypeDWARFDebugStrOffsets; break; case 'r': @@ -789,6 +802,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) { case lldb::eSectionTypeInvalid: case lldb::eSectionTypeDWARFDebugAbbrev: + case lldb::eSectionTypeDWARFDebugAddr: case lldb::eSectionTypeDWARFDebugAranges: case lldb::eSectionTypeDWARFDebugFrame: case lldb::eSectionTypeDWARFDebugInfo: @@ -799,6 +813,7 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) case lldb::eSectionTypeDWARFDebugPubTypes: case lldb::eSectionTypeDWARFDebugRanges: case lldb::eSectionTypeDWARFDebugStr: + case lldb::eSectionTypeDWARFDebugStrOffsets: case lldb::eSectionTypeDWARFAppleNames: case lldb::eSectionTypeDWARFAppleTypes: case lldb::eSectionTypeDWARFAppleNamespaces: @@ -806,10 +821,12 @@ IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp) err.Clear(); break; default: + const bool zero_memory = false; record.m_process_address = Malloc (record.m_size, record.m_alignment, record.m_permissions, eAllocationPolicyProcessOnly, + zero_memory, err); break; } @@ -877,12 +894,13 @@ IRExecutionUnit::AllocationRecord::dump (Log *log) if (!log) return; - log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)", + log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", (unsigned long long)m_host_address, (unsigned long long)m_size, (unsigned long long)m_process_address, (unsigned)m_alignment, - (unsigned)m_section_id); + (unsigned)m_section_id, + m_name.c_str()); } diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp deleted file mode 100644 index cf2a93b3ea7f..000000000000 --- a/source/Expression/IRForTarget.cpp +++ /dev/null @@ -1,2819 +0,0 @@ -//===-- IRForTarget.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/Expression/IRForTarget.h" - -#include "llvm/Support/raw_ostream.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/ValueSymbolTable.h" - -#include "clang/AST/ASTContext.h" - -#include "lldb/Core/dwarf.h" -#include "lldb/Core/ConstString.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRInterpreter.h" -#include "lldb/Host/Endian.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTType.h" -#include "lldb/Target/CPPLanguageRuntime.h" - -#include - -using namespace llvm; - -static char ID; - -IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) : - m_execution_unit(execution_unit), - m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()), - m_allocation(LLDB_INVALID_ADDRESS) -{ -} - -IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : - m_maker(maker), - m_values() -{ -} - -IRForTarget::FunctionValueCache::~FunctionValueCache() -{ -} - -llvm::Value * -IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) -{ - if (!m_values.count(function)) - { - llvm::Value *ret = m_maker(function); - m_values[function] = ret; - return ret; - } - return m_values[function]; -} - -lldb::addr_t -IRForTarget::StaticDataAllocator::Allocate() -{ - lldb_private::Error err; - - if (m_allocation != LLDB_INVALID_ADDRESS) - { - m_execution_unit.FreeNow(m_allocation); - m_allocation = LLDB_INVALID_ADDRESS; - } - - m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err); - - return m_allocation; -} - -lldb::TargetSP -IRForTarget::StaticDataAllocator::GetTarget() -{ - return m_execution_unit.GetTarget(); -} - -static llvm::Value * -FindEntryInstruction (llvm::Function *function) -{ - if (function->empty()) - return NULL; - - return function->getEntryBlock().getFirstNonPHIOrDbg(); -} - -IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, - bool resolve_vars, - lldb_private::IRExecutionUnit &execution_unit, - lldb_private::Stream *error_stream, - const char *func_name) : - ModulePass(ID), - m_resolve_vars(resolve_vars), - m_func_name(func_name), - m_module(NULL), - m_decl_map(decl_map), - m_data_allocator(execution_unit), - m_CFStringCreateWithBytes(NULL), - m_sel_registerName(NULL), - m_intptr_ty(NULL), - m_error_stream(error_stream), - m_result_store(NULL), - m_result_is_pointer(false), - m_reloc_placeholder(NULL), - m_entry_instruction_finder (FindEntryInstruction) -{ -} - -/* Handy utility functions used at several places in the code */ - -static std::string -PrintValue(const Value *value, bool truncate = false) -{ - std::string s; - if (value) - { - raw_string_ostream rso(s); - value->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - } - return s; -} - -static std::string -PrintType(const llvm::Type *type, bool truncate = false) -{ - std::string s; - raw_string_ostream rso(s); - type->print(rso); - rso.flush(); - if (truncate) - s.resize(s.length() - 1); - return s; -} - -IRForTarget::~IRForTarget() -{ -} - -bool -IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) -{ - llvm_function.setLinkage(GlobalValue::ExternalLinkage); - - std::string name = llvm_function.getName().str(); - - return true; -} - -IRForTarget::LookupResult -IRForTarget::GetFunctionAddress (llvm::Function *fun, - uint64_t &fun_addr, - lldb_private::ConstString &name, - Constant **&value_ptr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - fun_addr = LLDB_INVALID_ADDRESS; - name.Clear(); - value_ptr = NULL; - - if (fun->isIntrinsic()) - { - Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID(); - - switch (intrinsic_id) - { - default: - if (log) - log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str()); - - return LookupResult::Fail; - case Intrinsic::memcpy: - { - static lldb_private::ConstString g_memcpy_str ("memcpy"); - name = g_memcpy_str; - } - break; - case Intrinsic::memset: - { - static lldb_private::ConstString g_memset_str ("memset"); - name = g_memset_str; - } - break; - case Intrinsic::dbg_declare: - case Intrinsic::dbg_value: - return LookupResult::Ignore; - } - - if (log && name) - log->Printf("Resolved intrinsic name \"%s\"", name.GetCString()); - } - else - { - name.SetCStringWithLength (fun->getName().data(), fun->getName().size()); - } - - // Find the address of the function. - - clang::NamedDecl *fun_decl = DeclForGlobal (fun); - - if (fun_decl) - { - if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) - { - std::vector alternates; - bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); - if (!found_it) - { - if (log) - log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); - // Check for an alternate mangling for names from the standard library. - // For example, "std::basic_string<...>" has an alternate mangling scheme per - // the Itanium C++ ABI. - lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); - if (process_sp) - { - lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); - if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) - { - for (size_t i = 0; i < alternates.size(); ++i) - { - const lldb_private::ConstString &alternate_name = alternates[i]; - if (log) - log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", - name.GetCString(), alternate_name.GetCString()); - if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) - { - if (log) - log->Printf("Found address of function \"%s\" with alternate name \"%s\"", - name.GetCString(), alternate_name.GetCString()); - break; - } - } - } - } - } - - if (!found_it) - { - lldb_private::Mangled mangled_name(name); - if (m_error_stream) - { - if (mangled_name.GetMangledName()) - m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", - mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), - mangled_name.GetMangledName().GetCString()); - else - m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", - mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); - } - return LookupResult::Fail; - } - } - } - else - { - if (!m_decl_map->GetFunctionAddress (name, fun_addr)) - { - if (log) - log->Printf ("Metadataless function \"%s\" had no address", name.GetCString()); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString()); - - return LookupResult::Fail; - } - } - - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); - - return LookupResult::Success; -} - -llvm::Constant * -IRForTarget::BuildFunctionPointer (llvm::Type *type, - uint64_t ptr) -{ - PointerType *fun_ptr_ty = PointerType::getUnqual(type); - Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false); - return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); -} - -void -IRForTarget::RegisterFunctionMetadata(LLVMContext &context, - llvm::Value *function_ptr, - const char *name) -{ - for (llvm::User *user : function_ptr->users()) - { - if (Instruction *user_inst = dyn_cast(user)) - { - MDString* md_name = MDString::get(context, StringRef(name)); - - MDNode *metadata = MDNode::get(context, md_name); - - user_inst->setMetadata("lldb.call.realName", metadata); - } - else - { - RegisterFunctionMetadata (context, user, name); - } - } -} - -bool -IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - for (llvm::Module::iterator fi = llvm_module.begin(); - fi != llvm_module.end(); - ++fi) - { - Function *fun = fi; - - bool is_decl = fun->isDeclaration(); - - if (log) - log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str()); - - if (!is_decl) - continue; - - if (fun->use_empty()) - continue; // ignore - - uint64_t addr = LLDB_INVALID_ADDRESS; - lldb_private::ConstString name; - Constant **value_ptr = NULL; - - LookupResult result = GetFunctionAddress(fun, - addr, - name, - value_ptr); - - switch (result) - { - case LookupResult::Fail: - return false; // GetFunctionAddress reports its own errors - - case LookupResult::Ignore: - break; // Nothing to do - - case LookupResult::Success: - { - Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr); - - RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString()); - - if (value_ptr) - *value_ptr = value; - - // If we are replacing a function with the nobuiltin attribute, it may - // be called with the builtin attribute on call sites. Remove any such - // attributes since it's illegal to have a builtin call to something - // other than a nobuiltin function. - if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) { - llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin); - - for (auto u : fun->users()) { - if (auto call = dyn_cast(u)) { - call->removeAttribute(AttributeSet::FunctionIndex, builtin); - } - } - } - - fun->replaceAllUsesWith(value); - } - break; - } - } - - return true; -} - - -clang::NamedDecl * -IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) -{ - NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); - - if (!named_metadata) - return NULL; - - unsigned num_nodes = named_metadata->getNumOperands(); - unsigned node_index; - - for (node_index = 0; - node_index < num_nodes; - ++node_index) - { - llvm::MDNode *metadata_node = dyn_cast(named_metadata->getOperand(node_index)); - if (!metadata_node) - return NULL; - - if (metadata_node->getNumOperands() != 2) - continue; - - if (mdconst::dyn_extract_or_null(metadata_node->getOperand(0)) != global_val) - continue; - - ConstantInt *constant_int = mdconst::dyn_extract(metadata_node->getOperand(1)); - - if (!constant_int) - return NULL; - - uintptr_t ptr = constant_int->getZExtValue(); - - return reinterpret_cast(ptr); - } - - return NULL; -} - -clang::NamedDecl * -IRForTarget::DeclForGlobal (GlobalValue *global_val) -{ - return DeclForGlobal(global_val, m_module); -} - -bool -IRForTarget::CreateResultVariable (llvm::Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_resolve_vars) - return true; - - // Find the result variable. If it doesn't exist, we can give up right here. - - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); - - std::string result_name_str; - const char *result_name = NULL; - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - result_name_str = vi->first().str(); - const char *value_name = result_name_str.c_str(); - - if (strstr(value_name, "$__lldb_expr_result_ptr") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = true; - break; - } - - if (strstr(value_name, "$__lldb_expr_result") && - strncmp(value_name, "_ZGV", 4)) - { - result_name = value_name; - m_result_is_pointer = false; - break; - } - } - - if (!result_name) - { - if (log) - log->PutCString("Couldn't find result variable"); - - return true; - } - - if (log) - log->Printf("Result name: \"%s\"", result_name); - - Value *result_value = m_module->getNamedValue(result_name); - - if (!result_value) - { - if (log) - log->PutCString("Result variable had no data"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); - - return false; - } - - if (log) - log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); - - GlobalVariable *result_global = dyn_cast(result_value); - - if (!result_global) - { - if (log) - log->PutCString("Result variable isn't a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); - - return false; - } - - clang::NamedDecl *result_decl = DeclForGlobal (result_global); - if (!result_decl) - { - if (log) - log->PutCString("Result variable doesn't have a corresponding Decl"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); - - return false; - } - - if (log) - { - std::string decl_desc_str; - raw_string_ostream decl_desc_stream(decl_desc_str); - result_decl->print(decl_desc_stream); - decl_desc_stream.flush(); - - log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); - } - - clang::VarDecl *result_var = dyn_cast(result_decl); - if (!result_var) - { - if (log) - log->PutCString("Result variable Decl isn't a VarDecl"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); - - return false; - } - - // Get the next available result name from m_decl_map and create the persistent - // variable for it - - // If the result is an Lvalue, it is emitted as a pointer; see - // ASTResultSynthesizer::SynthesizeBodyResult. - if (m_result_is_pointer) - { - clang::QualType pointer_qual_type = result_var->getType(); - const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); - - const clang::PointerType *pointer_pointertype = pointer_type->getAs(); - const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs(); - - if (pointer_pointertype) - { - clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); - - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); - } - else if (pointer_objcobjpointertype) - { - clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); - - m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), - &result_decl->getASTContext()); - } - else - { - if (log) - log->PutCString("Expected result to have pointer type, but it did not"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); - - return false; - } - } - else - { - m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), - &result_decl->getASTContext()); - } - - - lldb::TargetSP target_sp (m_data_allocator.GetTarget()); - lldb_private::ExecutionContext exe_ctx (target_sp, true); - if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); - - if (log) - log->Printf("Result type has size 0"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", - type_desc_stream.GetData()); - return false; - } - - if (log) - { - lldb_private::StreamString type_desc_stream; - m_result_type.DumpTypeDescription(&type_desc_stream); - - log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); - } - - m_result_name = lldb_private::ConstString("$RESULT_NAME"); - - if (log) - log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, - m_result_name.GetCString(), - m_result_type.GetByteSize(nullptr)); - - // Construct a new result global and set up its metadata - - GlobalVariable *new_result_global = new GlobalVariable((*m_module), - result_global->getType()->getElementType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - m_result_name.GetCString ()); - - // It's too late in compilation to create a new VarDecl for this, but we don't - // need to. We point the metadata at the old VarDecl. This creates an odd - // anomaly: a variable with a Value whose name is something like $0 and a - // Decl whose name is $__lldb_expr_result. This condition is handled in - // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is - // fixed up. - - ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), - reinterpret_cast(result_decl), - false); - - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(new_result_global); - values[1] = ConstantAsMetadata::get(new_constant_int); - - ArrayRef value_ref(values, 2); - - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); - named_metadata->addOperand(persistent_global_md); - - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(result_global).c_str(), - PrintValue(new_result_global).c_str()); - - if (result_global->use_empty()) - { - // We need to synthesize a store for this variable, because otherwise - // there's nothing to put into its equivalent persistent variable. - - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); - - if (!first_entry_instruction) - return false; - - if (!result_global->hasInitializer()) - { - if (log) - log->Printf("Couldn't find initializer for unused variable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); - - return false; - } - - Constant *initializer = result_global->getInitializer(); - - StoreInst *synthesized_store = new StoreInst(initializer, - new_result_global, - first_entry_instruction); - - if (log) - log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); - } - else - { - result_global->replaceAllUsesWith(new_result_global); - } - - if (!m_decl_map->AddPersistentVariable(result_decl, - m_result_name, - m_result_type, - true, - m_result_is_pointer)) - return false; - - result_global->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, - llvm::GlobalVariable *cstr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Type *ns_str_ty = ns_str->getType(); - - Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); - Type *i32_ty = Type::getInt32Ty(m_module->getContext()); - Type *i8_ty = Type::getInt8Ty(m_module->getContext()); - - if (!m_CFStringCreateWithBytes) - { - lldb::addr_t CFStringCreateWithBytes_addr; - - static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); - - if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) - { - if (log) - log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); - - return false; - } - - if (log) - log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); - - // Build the function type: - // - // CFStringRef CFStringCreateWithBytes ( - // CFAllocatorRef alloc, - // const UInt8 *bytes, - // CFIndex numBytes, - // CFStringEncoding encoding, - // Boolean isExternalRepresentation - // ); - // - // We make the following substitutions: - // - // CFStringRef -> i8* - // CFAllocatorRef -> i8* - // UInt8 * -> i8* - // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) - // CFStringEncoding -> i32 - // Boolean -> i8 - - Type *arg_type_array[5]; - - arg_type_array[0] = i8_ptr_ty; - arg_type_array[1] = i8_ptr_ty; - arg_type_array[2] = m_intptr_ty; - arg_type_array[3] = i32_ty; - arg_type_array[4] = i8_ty; - - ArrayRef CFSCWB_arg_types(arg_type_array, 5); - - llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); - - // Build the constant containing the pointer to the function - PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); - Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); - m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); - } - - ConstantDataSequential *string_array = NULL; - - if (cstr) - string_array = dyn_cast(cstr->getInitializer()); - - Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); - Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); - Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); - Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ - Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ - - Value *argument_array[5]; - - argument_array[0] = alloc_arg; - argument_array[1] = bytes_arg; - argument_array[2] = numBytes_arg; - argument_array[3] = encoding_arg; - argument_array[4] = isExternal_arg; - - ArrayRef CFSCWB_arguments(argument_array, 5); - - FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { - return CallInst::Create(m_CFStringCreateWithBytes, - CFSCWB_arguments, - "CFStringCreateWithBytes", - llvm::cast(m_entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder)) - { - if (log) - log->PutCString("Couldn't replace the NSString with the result of the call"); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n"); - - return false; - } - - ns_str->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCConstStrings() -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); - - if (strstr(value_name_cstr, "_unnamed_cfstring_")) - { - Value *nsstring_value = vi->second; - - GlobalVariable *nsstring_global = dyn_cast(nsstring_value); - - if (!nsstring_global) - { - if (log) - log->PutCString("NSString variable is not a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); - - return false; - } - - if (!nsstring_global->hasInitializer()) - { - if (log) - log->PutCString("NSString variable does not have an initializer"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); - - return false; - } - - ConstantStruct *nsstring_struct = dyn_cast(nsstring_global->getInitializer()); - - if (!nsstring_struct) - { - if (log) - log->PutCString("NSString variable's initializer is not a ConstantStruct"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); - - return false; - } - - // We expect the following structure: - // - // struct { - // int *isa; - // int flags; - // char *str; - // long length; - // }; - - if (nsstring_struct->getNumOperands() != 4) - { - if (log) - log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); - - return false; - } - - Constant *nsstring_member = nsstring_struct->getOperand(2); - - if (!nsstring_member) - { - if (log) - log->PutCString("NSString initializer's str element was empty"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); - - return false; - } - - ConstantExpr *nsstring_expr = dyn_cast(nsstring_member); - - if (!nsstring_expr) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantExpr"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); - - return false; - } - - if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) - { - if (log) - log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); - - return false; - } - - Constant *nsstring_cstr = nsstring_expr->getOperand(0); - - GlobalVariable *cstr_global = dyn_cast(nsstring_cstr); - - if (!cstr_global) - { - if (log) - log->PutCString("NSString initializer's str element is not a GlobalVariable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); - - return false; - } - - if (!cstr_global->hasInitializer()) - { - if (log) - log->PutCString("NSString initializer's str element does not have an initializer"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); - - return false; - } - - /* - if (!cstr_array) - { - if (log) - log->PutCString("NSString initializer's str element is not a ConstantArray"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); - - return false; - } - - if (!cstr_array->isCString()) - { - if (log) - log->PutCString("NSString initializer's str element is not a C string array"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); - - return false; - } - */ - - ConstantDataArray *cstr_array = dyn_cast(cstr_global->getInitializer()); - - if (log) - { - if (cstr_array) - log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); - else - log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); - } - - if (!cstr_array) - cstr_global = NULL; - - if (!RewriteObjCConstString(nsstring_global, cstr_global)) - { - if (log) - log->PutCString("Error rewriting the constant string"); - - // We don't print an error message here because RewriteObjCConstString has done so for us. - - return false; - } - } - } - - for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); - vi != ve; - ++vi) - { - std::string value_name = vi->first().str(); - const char *value_name_cstr = value_name.c_str(); - - if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) - { - GlobalVariable *gv = dyn_cast(vi->second); - - if (!gv) - { - if (log) - log->PutCString("__CFConstantStringClassReference is not a global variable"); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); - - return false; - } - - gv->eraseFromParent(); - - break; - } - } - - return true; -} - -static bool IsObjCSelectorRef (Value *value) -{ - GlobalVariable *global_variable = dyn_cast(value); - - if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) - return false; - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::RewriteObjCSelector (Instruction* selector_load) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - LoadInst *load = dyn_cast(selector_load); - - if (!load) - return false; - - // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as - // - // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; - // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; - // - // where %obj is the object pointer and %tmp is the selector. - // - // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". - // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. - - // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target - - GlobalVariable *_objc_selector_references_ = dyn_cast(load->getPointerOperand()); - - if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) - return false; - - Constant *osr_initializer = _objc_selector_references_->getInitializer(); - - ConstantExpr *osr_initializer_expr = dyn_cast(osr_initializer); - - if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) - return false; - - Value *osr_initializer_base = osr_initializer_expr->getOperand(0); - - if (!osr_initializer_base) - return false; - - // Find the string's initializer (a ConstantArray) and get the string from it - - GlobalVariable *_objc_meth_var_name_ = dyn_cast(osr_initializer_base); - - if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) - return false; - - Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); - - ConstantDataArray *omvn_initializer_array = dyn_cast(omvn_initializer); - - if (!omvn_initializer_array->isString()) - return false; - - std::string omvn_initializer_string = omvn_initializer_array->getAsString(); - - if (log) - log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); - - // Construct a call to sel_registerName - - if (!m_sel_registerName) - { - lldb::addr_t sel_registerName_addr; - - static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); - if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr)) - return false; - - if (log) - log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); - - // Build the function type: struct objc_selector *sel_registerName(uint8_t*) - - // The below code would be "more correct," but in actuality what's required is uint8_t* - //Type *sel_type = StructType::get(m_module->getContext()); - //Type *sel_ptr_type = PointerType::getUnqual(sel_type); - Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); - - Type *type_array[1]; - - type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); - - ArrayRef srN_arg_types(type_array, 1); - - llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); - - // Build the constant containing the pointer to the function - PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); - Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); - m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); - } - - Value *argument_array[1]; - - Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); - - argument_array[0] = omvn_pointer; - - ArrayRef srN_arguments(argument_array, 1); - - CallInst *srN_call = CallInst::Create(m_sel_registerName, - srN_arguments, - "sel_registerName", - selector_load); - - // Replace the load with the call in all users - - selector_load->replaceAllUsesWith(srN_call); - - selector_load->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - BasicBlock::iterator ii; - - typedef SmallVector InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList selector_loads; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (LoadInst *load = dyn_cast(&inst)) - if (IsObjCSelectorRef(load->getPointerOperand())) - selector_loads.push_back(&inst); - } - - InstrIterator iter; - - for (iter = selector_loads.begin(); - iter != selector_loads.end(); - ++iter) - { - if (!RewriteObjCSelector(*iter)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); - - if (log) - log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); - - return false; - } - } - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - AllocaInst *alloc = dyn_cast(persistent_alloc); - - MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); - - if (!alloc_md || !alloc_md->getNumOperands()) - return false; - - ConstantInt *constant_int = mdconst::dyn_extract(alloc_md->getOperand(0)); - - if (!constant_int) - return false; - - // We attempt to register this as a new persistent variable with the DeclMap. - - uintptr_t ptr = constant_int->getZExtValue(); - - clang::VarDecl *decl = reinterpret_cast(ptr); - - lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), - &decl->getASTContext()); - - StringRef decl_name (decl->getName()); - lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); - if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) - return false; - - GlobalVariable *persistent_global = new GlobalVariable((*m_module), - alloc->getType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, - NULL, /* no initializer */ - alloc->getName().str().c_str()); - - // What we're going to do here is make believe this was a regular old external - // variable. That means we need to make the metadata valid. - - NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); - - llvm::Metadata *values[2]; - values[0] = ConstantAsMetadata::get(persistent_global); - values[1] = ConstantAsMetadata::get(constant_int); - - ArrayRef value_ref(values, 2); - - MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); - named_metadata->addOperand(persistent_global_md); - - // Now, since the variable is a pointer variable, we will drop in a load of that - // pointer variable. - - LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); - - if (log) - log->Printf("Replacing \"%s\" with \"%s\"", - PrintValue(alloc).c_str(), - PrintValue(persistent_load).c_str()); - - alloc->replaceAllUsesWith(persistent_load); - alloc->eraseFromParent(); - - return true; -} - -bool -IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) -{ - if (!m_resolve_vars) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - BasicBlock::iterator ii; - - typedef SmallVector InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList pvar_allocs; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (AllocaInst *alloc = dyn_cast(&inst)) - { - llvm::StringRef alloc_name = alloc->getName(); - - if (alloc_name.startswith("$") && - !alloc_name.startswith("$__lldb")) - { - if (alloc_name.find_first_of("0123456789") == 1) - { - if (log) - log->Printf("Rejecting a numeric persistent variable."); - - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); - - return false; - } - - pvar_allocs.push_back(alloc); - } - } - } - - InstrIterator iter; - - for (iter = pvar_allocs.begin(); - iter != pvar_allocs.end(); - ++iter) - { - if (!RewritePersistentAlloc(*iter)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); - - if (log) - log->PutCString("Couldn't rewrite the creation of a persistent variable"); - - return false; - } - } - - return true; -} - -bool -IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) -{ - if (!initializer) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log && log->GetVerbose()) - log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); - - Type *initializer_type = initializer->getType(); - - if (ConstantInt *int_initializer = dyn_cast(initializer)) - { - memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - else if (ConstantDataArray *array_initializer = dyn_cast(initializer)) - { - if (array_initializer->isString()) - { - std::string array_initializer_string = array_initializer->getAsString(); - memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); - } - else - { - ArrayType *array_initializer_type = array_initializer->getType(); - Type *array_element_type = array_initializer_type->getElementType(); - - size_t element_size = m_target_data->getTypeAllocSize(array_element_type); - - for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) - { - Value *operand_value = array_initializer->getOperand(i); - Constant *operand_constant = dyn_cast(operand_value); - - if (!operand_constant) - return false; - - if (!MaterializeInitializer(data + (i * element_size), operand_constant)) - return false; - } - } - return true; - } - else if (ConstantStruct *struct_initializer = dyn_cast(initializer)) - { - StructType *struct_initializer_type = struct_initializer->getType(); - const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); - - for (unsigned i = 0; - i < struct_initializer->getNumOperands(); - ++i) - { - if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) - return false; - } - return true; - } - else if (isa(initializer)) - { - memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); - return true; - } - return false; -} - -bool -IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable) -{ - if (GlobalVariable::isExternalLinkage(global_variable->getLinkage())) - return false; - - if (global_variable == m_reloc_placeholder) - return true; - - uint64_t offset = m_data_allocator.GetStream().GetSize(); - - llvm::Type *variable_type = global_variable->getType(); - - Constant *initializer = global_variable->getInitializer(); - - llvm::Type *initializer_type = initializer->getType(); - - size_t size = m_target_data->getTypeAllocSize(initializer_type); - size_t align = m_target_data->getPrefTypeAlignment(initializer_type); - - const size_t mask = (align - 1); - uint64_t aligned_offset = (offset + mask) & ~mask; - m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); - offset = aligned_offset; - - lldb_private::DataBufferHeap data(size, '\0'); - - if (initializer) - if (!MaterializeInitializer(data.GetBytes(), initializer)) - return false; - - m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize()); - - Constant *new_pointer = BuildRelocation(variable_type, offset); - - global_variable->replaceAllUsesWith(new_pointer); - - global_variable->eraseFromParent(); - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); - - if (ConstantExpr *constant_expr = dyn_cast(llvm_value_ptr)) - { - switch (constant_expr->getOpcode()) - { - default: - break; - case Instruction::GetElementPtr: - case Instruction::BitCast: - Value *s = constant_expr->getOperand(0); - if (!MaybeHandleVariable(s)) - return false; - } - } - else if (GlobalVariable *global_variable = dyn_cast(llvm_value_ptr)) - { - if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) - return MaterializeInternalVariable(global_variable); - - clang::NamedDecl *named_decl = DeclForGlobal(global_variable); - - if (!named_decl) - { - if (IsObjCSelectorRef(llvm_value_ptr)) - return true; - - if (!global_variable->hasExternalLinkage()) - return true; - - if (log) - log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); - - return false; - } - - std::string name (named_decl->getName().str()); - - clang::ValueDecl *value_decl = dyn_cast(named_decl); - if (value_decl == NULL) - return false; - - lldb_private::ClangASTType clang_type(&value_decl->getASTContext(), value_decl->getType()); - - const Type *value_type = NULL; - - if (name[0] == '$') - { - // The $__lldb_expr_result name indicates the return value has allocated as - // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, - // accesses to this static variable need to be redirected to the result of dereferencing - // a pointer that is passed in as one of the arguments. - // - // Consequently, when reporting the size of the type, we report a pointer type pointing - // to the type of $__lldb_expr_result, not the type itself. - // - // We also do this for any user-declared persistent variables. - clang_type = clang_type.GetPointerType(); - value_type = PointerType::get(global_variable->getType(), 0); - } - else - { - value_type = global_variable->getType(); - } - - const uint64_t value_size = clang_type.GetByteSize(nullptr); - lldb::offset_t value_alignment = (clang_type.GetTypeBitAlign() + 7ull) / 8ull; - - if (log) - { - log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", - name.c_str(), - clang_type.GetQualType().getAsString().c_str(), - 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)) - { - if (!global_variable->hasExternalLinkage()) - return true; - else if (HandleSymbol (global_variable)) - return true; - else - return false; - } - } - else if (dyn_cast(llvm_value_ptr)) - { - if (log) - log->Printf("Function pointers aren't handled right now"); - - return false; - } - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::HandleSymbol (Value *symbol) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - lldb_private::ConstString name(symbol->getName().str().c_str()); - - lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); - - if (symbol_addr == LLDB_INVALID_ADDRESS) - { - if (log) - log->Printf ("Symbol \"%s\" had no address", name.GetCString()); - - return false; - } - - if (log) - log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); - - Type *symbol_type = symbol->getType(); - - Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); - - Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); - - if (log) - log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); - - symbol->replaceAllUsesWith(symbol_addr_ptr); - - return true; -} - -bool -IRForTarget::MaybeHandleCallArguments (CallInst *Old) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); - - for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); - op_index < num_ops; - ++op_index) - if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); - - return false; - } - - return true; -} - -bool -IRForTarget::HandleObjCClass(Value *classlist_reference) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - GlobalVariable *global_variable = dyn_cast(classlist_reference); - - if (!global_variable) - return false; - - Constant *initializer = global_variable->getInitializer(); - - if (!initializer) - return false; - - if (!initializer->hasName()) - return false; - - StringRef name(initializer->getName()); - lldb_private::ConstString name_cstr(name.str().c_str()); - lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); - - if (log) - log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); - - if (class_ptr == LLDB_INVALID_ADDRESS) - return false; - - if (global_variable->use_empty()) - return false; - - SmallVector load_instructions; - - for (llvm::User *u : global_variable->users()) - { - if (LoadInst *load_instruction = dyn_cast(u)) - load_instructions.push_back(load_instruction); - } - - if (load_instructions.empty()) - return false; - - Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); - - for (LoadInst *load_instruction : load_instructions) - { - Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); - - load_instruction->replaceAllUsesWith(class_bitcast); - - load_instruction->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) -{ - BasicBlock::iterator ii; - - std::vector calls_to_remove; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - CallInst *call = dyn_cast(&inst); - - // MaybeHandleCallArguments handles error reporting; we are silent here - if (!call) - continue; - - bool remove = false; - - llvm::Function *func = call->getCalledFunction(); - - if (func && func->getName() == "__cxa_atexit") - remove = true; - - llvm::Value *val = call->getCalledValue(); - - if (val && val->getName() == "__cxa_atexit") - remove = true; - - if (remove) - calls_to_remove.push_back(call); - } - - for (std::vector::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); - ci != ce; - ++ci) - { - (*ci)->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::ResolveCalls(BasicBlock &basic_block) -{ - ///////////////////////////////////////////////////////////////////////// - // Prepare the current basic block for execution in the remote process - // - - BasicBlock::iterator ii; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - CallInst *call = dyn_cast(&inst); - - // MaybeHandleCallArguments handles error reporting; we are silent here - if (call && !MaybeHandleCallArguments(call)) - return false; - } - - return true; -} - -bool -IRForTarget::ResolveExternals (Function &llvm_function) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - for (GlobalVariable &global_var : m_module->globals()) - { - std::string global_name = global_var.getName().str(); - - if (log) - log->Printf("Examining %s, DeclForGlobalValue returns %p", - global_name.c_str(), - static_cast(DeclForGlobal(&global_var))); - - if (global_name.find("OBJC_IVAR") == 0) - { - if (!HandleSymbol(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); - - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); - - return false; - } - } - else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) - { - if (!HandleObjCClass(&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); - - return false; - } - } - else if (DeclForGlobal(&global_var)) - { - if (!MaybeHandleVariable (&global_var)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); - - return false; - } - } - } - - return true; -} - -bool -IRForTarget::ReplaceStrings () -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - typedef std::map OffsetsTy; - - OffsetsTy offsets; - - for (GlobalVariable &gv : m_module->globals()) - { - if (!gv.hasInitializer()) - continue; - - Constant *gc = gv.getInitializer(); - - std::string str; - - if (gc->isNullValue()) - { - Type *gc_type = gc->getType(); - - ArrayType *gc_array_type = dyn_cast(gc_type); - - if (!gc_array_type) - continue; - - Type *gc_element_type = gc_array_type->getElementType(); - - IntegerType *gc_integer_type = dyn_cast(gc_element_type); - - if (gc_integer_type->getBitWidth() != 8) - continue; - - str = ""; - } - else - { - ConstantDataArray *gc_array = dyn_cast(gc); - - if (!gc_array) - continue; - - if (!gc_array->isCString()) - continue; - - if (log) - log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str()); - - str = gc_array->getAsString(); - } - - offsets[&gv] = m_data_allocator.GetStream().GetSize(); - - m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1); - } - - Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); - - for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end(); - oi != oe; - ++oi) - { - GlobalVariable *gv = oi->first; - size_t offset = oi->second; - - Constant *new_initializer = BuildRelocation(char_ptr_ty, offset); - - if (log) - log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str()); - - for (llvm::User *u : gv->users()) - { - if (log) - log->Printf("Found use %s", PrintValue(u).c_str()); - - ConstantExpr *const_expr = dyn_cast(u); - StoreInst *store_inst = dyn_cast(u); - - if (const_expr) - { - if (const_expr->getOpcode() != Instruction::GetElementPtr) - { - if (log) - log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str()); - - return false; - } - - Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType()); - Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast); - - const_expr->replaceAllUsesWith(new_gep); - } - else if (store_inst) - { - Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType()); - - store_inst->setOperand(0, bit_cast); - } - else - { - if (log) - log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str()); - - return false; - } - } - - gv->eraseFromParent(); - } - - return true; -} - -bool -IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - typedef SmallVector ConstantList; - typedef SmallVector UserList; - typedef ConstantList::iterator ConstantIterator; - typedef UserList::iterator UserIterator; - - ConstantList static_constants; - UserList static_users; - - for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end(); - ii != ie; - ++ii) - { - llvm::Instruction &inst = *ii; - - for (Value *operand_val : inst.operand_values()) - { - ConstantFP *operand_constant_fp = dyn_cast(operand_val); - - if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/) - { - static_constants.push_back(operand_val); - static_users.push_back(ii); - } - } - } - - ConstantIterator constant_iter; - UserIterator user_iter; - - for (constant_iter = static_constants.begin(), user_iter = static_users.begin(); - constant_iter != static_constants.end(); - ++constant_iter, ++user_iter) - { - Value *operand_val = *constant_iter; - llvm::Instruction *inst = *user_iter; - - ConstantFP *operand_constant_fp = dyn_cast(operand_val); - - if (operand_constant_fp) - { - Type *operand_type = operand_constant_fp->getType(); - - APFloat operand_apfloat = operand_constant_fp->getValueAPF(); - APInt operand_apint = operand_apfloat.bitcastToAPInt(); - - const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData(); - size_t operand_data_size = operand_apint.getBitWidth() / 8; - - if (log) - { - std::string s; - raw_string_ostream ss(s); - for (size_t index = 0; - index < operand_data_size; - ++index) - { - ss << (uint32_t)operand_raw_data[index]; - ss << " "; - } - ss.flush(); - - log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str()); - } - - lldb_private::DataBufferHeap data(operand_data_size, 0); - - if (lldb::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder()) - { - uint8_t *data_bytes = data.GetBytes(); - - for (size_t index = 0; - index < operand_data_size; - ++index) - { - data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)]; - } - } - else - { - memcpy(data.GetBytes(), operand_raw_data, operand_data_size); - } - - uint64_t offset = m_data_allocator.GetStream().GetSize(); - - size_t align = m_target_data->getPrefTypeAlignment(operand_type); - - const size_t mask = (align - 1); - uint64_t aligned_offset = (offset + mask) & ~mask; - m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); - - m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size); - - llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo(); - - Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset); - - llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst); - - operand_constant_fp->replaceAllUsesWith(fp_load); - } - } - - return true; -} - -static bool isGuardVariableRef(Value *V) -{ - Constant *Old = NULL; - - if (!(Old = dyn_cast(V))) - return false; - - ConstantExpr *CE = NULL; - - if ((CE = dyn_cast(V))) - { - if (CE->getOpcode() != Instruction::BitCast) - return false; - - Old = CE->getOperand(0); - } - - GlobalVariable *GV = dyn_cast(Old); - - if (!GV || !GV->hasName() || - (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable - !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable - { - return false; - } - - return true; -} - -void -IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) -{ - Constant *zero(Constant::getNullValue(guard_load->getType())); - guard_load->replaceAllUsesWith(zero); - guard_load->eraseFromParent(); -} - -static void ExciseGuardStore(Instruction* guard_store) -{ - guard_store->eraseFromParent(); -} - -bool -IRForTarget::RemoveGuards(BasicBlock &basic_block) -{ - /////////////////////////////////////////////////////// - // Eliminate any reference to guard variables found. - // - - BasicBlock::iterator ii; - - typedef SmallVector InstrList; - typedef InstrList::iterator InstrIterator; - - InstrList guard_loads; - InstrList guard_stores; - - for (ii = basic_block.begin(); - ii != basic_block.end(); - ++ii) - { - Instruction &inst = *ii; - - if (LoadInst *load = dyn_cast(&inst)) - if (isGuardVariableRef(load->getPointerOperand())) - guard_loads.push_back(&inst); - - if (StoreInst *store = dyn_cast(&inst)) - if (isGuardVariableRef(store->getPointerOperand())) - guard_stores.push_back(&inst); - } - - InstrIterator iter; - - for (iter = guard_loads.begin(); - iter != guard_loads.end(); - ++iter) - TurnGuardLoadIntoZero(*iter); - - for (iter = guard_stores.begin(); - iter != guard_stores.end(); - ++iter) - ExciseGuardStore(*iter); - - return true; -} - -// This function does not report errors; its callers are responsible. -bool -IRForTarget::UnfoldConstant(Constant *old_constant, - FunctionValueCache &value_maker, - FunctionValueCache &entry_instruction_finder) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - SmallVector users; - - // We do this because the use list might change, invalidating our iterator. - // Much better to keep a work list ourselves. - for (llvm::User *u : old_constant->users()) - users.push_back(u); - - for (size_t i = 0; - i < users.size(); - ++i) - { - User *user = users[i]; - - if (Constant *constant = dyn_cast(user)) - { - // synthesize a new non-constant equivalent of the constant - - if (ConstantExpr *constant_expr = dyn_cast(constant)) - { - switch (constant_expr->getOpcode()) - { - default: - if (log) - log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); - return false; - case Instruction::BitCast: - { - FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - // UnaryExpr - // OperandList[0] is value - - if (constant_expr->getOperand(0) != old_constant) - return constant_expr; - - return new BitCastInst(value_maker.GetValue(function), - constant_expr->getType(), - "", - llvm::cast(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder)) - return false; - } - break; - case Instruction::GetElementPtr: - { - // GetElementPtrConstantExpr - // OperandList[0] is base - // OperandList[1]... are indices - - FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { - Value *ptr = constant_expr->getOperand(0); - - if (ptr == old_constant) - ptr = value_maker.GetValue(function); - - std::vector index_vector; - - unsigned operand_index; - unsigned num_operands = constant_expr->getNumOperands(); - - for (operand_index = 1; - operand_index < num_operands; - ++operand_index) - { - Value *operand = constant_expr->getOperand(operand_index); - - if (operand == old_constant) - operand = value_maker.GetValue(function); - - index_vector.push_back(operand); - } - - ArrayRef indices(index_vector); - - return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast(entry_instruction_finder.GetValue(function))); - }); - - if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) - return false; - } - break; - } - } - else - { - if (log) - log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); - return false; - } - } - else - { - if (Instruction *inst = llvm::dyn_cast(user)) - { - inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); - } - else - { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); - return false; - } - } - } - - if (!isa(old_constant)) - { - old_constant->destroyConstant(); - } - - return true; -} - -bool -IRForTarget::ReplaceVariables (Function &llvm_function) -{ - if (!m_resolve_vars) - return true; - - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_decl_map->DoStructLayout(); - - if (log) - log->Printf("Element arrangement:"); - - uint32_t num_elements; - uint32_t element_index; - - size_t size; - lldb::offset_t alignment; - - if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) - return false; - - Function::arg_iterator iter(llvm_function.getArgumentList().begin()); - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); - - return false; - } - - Argument *argument = iter; - - if (argument->getName().equals("this")) - { - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); - - return false; - } - - argument = iter; - } - else if (argument->getName().equals("self")) - { - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); - - return false; - } - - if (!iter->getName().equals("_cmd")) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); - - return false; - } - - ++iter; - - if (iter == llvm_function.getArgumentList().end()) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); - - return false; - } - - argument = iter; - } - - if (!argument->getName().equals("$__lldb_arg")) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); - - return false; - } - - if (log) - log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); - - BasicBlock &entry_block(llvm_function.getEntryBlock()); - Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); - - if (!FirstEntryInstruction) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); - - return false; - } - - LLVMContext &context(m_module->getContext()); - IntegerType *offset_type(Type::getInt32Ty(context)); - - if (!offset_type) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); - - return false; - } - - for (element_index = 0; element_index < num_elements; ++element_index) - { - const clang::NamedDecl *decl = NULL; - Value *value = NULL; - lldb::offset_t offset; - lldb_private::ConstString name; - - if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) - { - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete"); - - return false; - } - - if (log) - log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, - name.GetCString(), - decl->getNameAsString().c_str(), - offset); - - if (value) - { - if (log) - log->Printf(" Replacing [%s]", PrintValue(value).c_str()); - - FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { - // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result - // variable is an rvalue, we have to synthesize a dereference of the appropriate structure - // entry in order to produce the static variable that the AST thinks it is accessing. - - llvm::Instruction *entry_instruction = llvm::cast(m_entry_instruction_finder.GetValue(function)); - - ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); - GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, - argument, - offset_int, - "", - entry_instruction); - - if (name == m_result_name && !m_result_is_pointer) - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, - value->getType()->getPointerTo(), - "", - entry_instruction); - - LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); - - return load; - } - else - { - BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); - - return bit_cast; - } - }); - - if (Constant *constant = dyn_cast(value)) - { - UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder); - } - else if (Instruction *instruction = dyn_cast(value)) - { - value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); - } - else - { - if (log) - log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); - return false; - } - - if (GlobalVariable *var = dyn_cast(value)) - var->eraseFromParent(); - } - } - - if (log) - log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); - - return true; -} - -llvm::Constant * -IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) -{ - llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); - - llvm::Constant *offset_array[1]; - - offset_array[0] = offset_int; - - llvm::ArrayRef offsets(offset_array, 1); - llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); - llvm::Type *char_pointer_type = char_type->getPointerTo(); - - llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); - llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); - llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); - - return reloc_bitcast; -} - -bool -IRForTarget::CompleteDataAllocation () -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (!m_data_allocator.GetStream().GetSize()) - return true; - - lldb::addr_t allocation = m_data_allocator.Allocate(); - - if (log) - { - if (allocation) - log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation); - else - log->Printf("Failed to allocate static data"); - } - - if (!allocation || allocation == LLDB_INVALID_ADDRESS) - return false; - - Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation); - Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext())); - - m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast); - - m_reloc_placeholder->eraseFromParent(); - - return true; -} - -bool -IRForTarget::StripAllGVs (Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - std::vector global_vars; - std::seterased_vars; - - bool erased = true; - - while (erased) - { - erased = false; - - for (GlobalVariable &global_var : llvm_module.globals()) - { - global_var.removeDeadConstantUsers(); - - if (global_var.use_empty()) - { - if (log) - log->Printf("Did remove %s", - PrintValue(&global_var).c_str()); - global_var.eraseFromParent(); - erased = true; - break; - } - } - } - - for (GlobalVariable &global_var : llvm_module.globals()) - { - GlobalValue::user_iterator ui = global_var.user_begin(); - - if (log) - log->Printf("Couldn't remove %s because of %s", - PrintValue(&global_var).c_str(), - PrintValue(*ui).c_str()); - } - - return true; -} - -bool -IRForTarget::runOnModule (Module &llvm_module) -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - m_module = &llvm_module; - m_target_data.reset(new DataLayout(m_module)); - m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); - - if (log) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); - } - - Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str())); - - if (!main_function) - { - if (log) - log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); - - if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); - - return false; - } - - if (!FixFunctionLinkage (*main_function)) - { - if (log) - log->Printf("Couldn't fix the linkage for the function"); - - return false; - } - - llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); - - m_reloc_placeholder = new llvm::GlobalVariable((*m_module), - int8_ty, - false /* IsConstant */, - GlobalVariable::InternalLinkage, - Constant::getNullValue(int8_ty), - "reloc_placeholder", - NULL /* InsertBefore */, - GlobalVariable::NotThreadLocal /* ThreadLocal */, - 0 /* AddressSpace */); - - //////////////////////////////////////////////////////////// - // Replace $__lldb_expr_result with a persistent variable - // - - if (!CreateResultVariable(*main_function)) - { - if (log) - log->Printf("CreateResultVariable() failed"); - - // CreateResultVariable() reports its own errors, so we don't do so here - - return false; - } - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - if (function->begin() == function->end()) - continue; - - Function::iterator bbi; - - for (bbi = function->begin(); - bbi != function->end(); - ++bbi) - { - if (!RemoveGuards(*bbi)) - { - if (log) - log->Printf("RemoveGuards() failed"); - - // RemoveGuards() reports its own errors, so we don't do so here - - return false; - } - - if (!RewritePersistentAllocs(*bbi)) - { - if (log) - log->Printf("RewritePersistentAllocs() failed"); - - // RewritePersistentAllocs() reports its own errors, so we don't do so here - - return false; - } - - if (!RemoveCXAAtExit(*bbi)) - { - if (log) - log->Printf("RemoveCXAAtExit() failed"); - - // RemoveCXAAtExit() reports its own errors, so we don't do so here - - return false; - } - } - } - - /////////////////////////////////////////////////////////////////////////////// - // Fix all Objective-C constant strings to use NSStringWithCString:encoding: - // - - if (!RewriteObjCConstStrings()) - { - if (log) - log->Printf("RewriteObjCConstStrings() failed"); - - // RewriteObjCConstStrings() reports its own errors, so we don't do so here - - return false; - } - - /////////////////////////////// - // Resolve function pointers - // - - if (!ResolveFunctionPointers(llvm_module)) - { - if (log) - log->Printf("ResolveFunctionPointers() failed"); - - // ResolveFunctionPointers() reports its own errors, so we don't do so here - - return false; - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!RewriteObjCSelectors(*bbi)) - { - if (log) - log->Printf("RewriteObjCSelectors() failed"); - - // RewriteObjCSelectors() reports its own errors, so we don't do so here - - return false; - } - } - } - - for (Module::iterator fi = m_module->begin(), fe = m_module->end(); - fi != fe; - ++fi) - { - llvm::Function *function = fi; - - for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); - bbi != bbe; - ++bbi) - { - if (!ResolveCalls(*bbi)) - { - if (log) - log->Printf("ResolveCalls() failed"); - - // ResolveCalls() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceStaticLiterals(*bbi)) - { - if (log) - log->Printf("ReplaceStaticLiterals() failed"); - - return false; - } - } - } - - //////////////////////////////////////////////////////////////////////// - // Run function-level passes that only make sense on the main function - // - - if (!ResolveExternals(*main_function)) - { - if (log) - log->Printf("ResolveExternals() failed"); - - // ResolveExternals() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceVariables(*main_function)) - { - if (log) - log->Printf("ReplaceVariables() failed"); - - // ReplaceVariables() reports its own errors, so we don't do so here - - return false; - } - - if (!ReplaceStrings()) - { - if (log) - log->Printf("ReplaceStrings() failed"); - - return false; - } - - if (!CompleteDataAllocation()) - { - if (log) - log->Printf("CompleteDataAllocation() failed"); - - return false; - } - - if (!StripAllGVs(llvm_module)) - { - if (log) - log->Printf("StripAllGVs() failed"); - } - - if (log && log->GetVerbose()) - { - std::string s; - raw_string_ostream oss(s); - - m_module->print(oss, NULL); - - oss.flush(); - - log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); - } - - return true; -} - -void -IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) -{ -} - -PassManagerType -IRForTarget::getPotentialPassManagerType() const -{ - return PMT_ModulePassManager; -} diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp index 926d1f22b6aa..a2b0c5b86851 100644 --- a/source/Expression/IRInterpreter.cpp +++ b/source/Expression/IRInterpreter.cpp @@ -365,7 +365,7 @@ public: const uint64_t *raw_data = resolved_value.getRawData(); - buffer.PutRawBytes(raw_data, constant_size, lldb::endian::InlHostByteOrder()); + buffer.PutRawBytes(raw_data, constant_size, lldb_private::endian::InlHostByteOrder()); lldb_private::Error write_error; @@ -498,7 +498,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, default: { if (log) - log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str()); + log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -522,7 +522,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, if (!CanIgnoreCall(call_inst) && !support_function_calls) { if (log) - log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str()); + log->Printf("Unsupported instruction: %s", PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); return false; @@ -547,7 +547,7 @@ IRInterpreter::CanInterpret (llvm::Module &module, default: { if (log) - log->Printf("Unsupported ICmp predicate: %s", PrintValue(ii).c_str()); + log->Printf("Unsupported ICmp predicate: %s", PrintValue(&*ii).c_str()); error.SetErrorToGenericError(); error.SetErrorString(unsupported_opcode_error); @@ -655,7 +655,7 @@ IRInterpreter::Interpret (llvm::Module &module, ai != ae; ++ai, ++arg_index) { - if (args.size() < static_cast(arg_index)) + if (args.size() <= static_cast(arg_index)) { error.SetErrorString ("Not enough arguments passed in to function"); return false; @@ -663,16 +663,16 @@ IRInterpreter::Interpret (llvm::Module &module, lldb::addr_t ptr = args[arg_index]; - frame.MakeArgument(ai, ptr); + frame.MakeArgument(&*ai, ptr); } uint32_t num_insts = 0; - frame.Jump(function.begin()); + frame.Jump(&function.front()); while (frame.m_ii != frame.m_ie && (++num_insts < 4096)) { - const Instruction *inst = frame.m_ii; + const Instruction *inst = &*frame.m_ii; if (log) log->Printf("Interpreting %s", PrintValue(inst).c_str()); diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp index 4733b16d5f1c..e96bddde7cbb 100644 --- a/source/Expression/IRMemoryMap.cpp +++ b/source/Expression/IRMemoryMap.cpp @@ -47,7 +47,7 @@ IRMemoryMap::~IRMemoryMap () } lldb::addr_t -IRMemoryMap::FindSpace (size_t size) +IRMemoryMap::FindSpace (size_t size, bool zero_memory) { lldb::TargetSP target_sp = m_target_wp.lock(); lldb::ProcessSP process_sp = m_process_wp.lock(); @@ -60,7 +60,10 @@ IRMemoryMap::FindSpace (size_t size) { Error alloc_error; - ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); + if (!zero_memory) + ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); + else + ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error); if (!alloc_error.Success()) return LLDB_INVALID_ADDRESS; @@ -225,7 +228,7 @@ IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc, } lldb::addr_t -IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error) +IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error) { lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); error.Clear(); @@ -263,7 +266,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false"); if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { - allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); + if (!zero_memory) + allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); + else + allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); + if (!error.Success()) return LLDB_INVALID_ADDRESS; } @@ -287,7 +294,11 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc { if (process_sp->CanJIT() && process_sp->IsAlive()) { - allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); + if (!zero_memory) + allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); + else + allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); + if (!error.Success()) return LLDB_INVALID_ADDRESS; } diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp new file mode 100644 index 000000000000..eff0a2dc30d6 --- /dev/null +++ b/source/Expression/LLVMUserExpression.cpp @@ -0,0 +1,363 @@ +//===-- LLVMUserExpression.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 + +// Project includes +#include "lldb/Expression/LLVMUserExpression.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +using namespace lldb_private; + +LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options) + : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options), + m_stack_frame_bottom(LLDB_INVALID_ADDRESS), + m_stack_frame_top(LLDB_INVALID_ADDRESS), + m_transformed_text(), + m_execution_unit_sp(), + m_materializer_ap(), + m_jit_module_wp(), + m_enforce_valid_object(true), + m_in_cplusplus_method(false), + m_in_objectivec_method(false), + m_in_static_method(false), + m_needs_object_ptr(false), + m_const_object(false), + m_target(NULL), + m_can_interpret(false), + m_materialized_address(LLDB_INVALID_ADDRESS) +{ +} + +LLVMUserExpression::~LLVMUserExpression() +{ + if (m_target) + { + lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock()); + if (jit_module_sp) + m_target->GetImages().Remove(jit_module_sp); + } +} + +lldb::ExpressionResults +LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +{ + // The expression log is quite verbose, and if you're just tracking the execution of the + // expression, it's quite convenient to have these logs come out with the STEP log as well. + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) + { + lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; + + if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address)) + { + error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; + + if (m_can_interpret) + { + llvm::Module *module = m_execution_unit_sp->GetModule(); + llvm::Function *function = m_execution_unit_sp->GetFunction(); + + if (!module || !function) + { + error_stream.Printf("Supposed to interpret, but nothing is there"); + return lldb::eExpressionSetupError; + } + + Error interpreter_error; + + std::vector args; + + if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + { + error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + function_stack_bottom = m_stack_frame_bottom; + function_stack_top = m_stack_frame_top; + + IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error, + function_stack_bottom, function_stack_top, exe_ctx); + + if (!interpreter_error.Success()) + { + error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); + return lldb::eExpressionDiscarded; + } + } + else + { + if (!exe_ctx.HasThreadScope()) + { + error_stream.Printf("UserExpression::Execute called with no thread selected."); + return lldb::eExpressionSetupError; + } + + Address wrapper_address(m_jit_start_addr); + + std::vector args; + + if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + { + error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address, + args, options, shared_ptr_to_me)); + + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + return lldb::eExpressionSetupError; + + ThreadPlanCallUserExpression *user_expression_plan = + static_cast(call_plan_sp.get()); + + lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); + + function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); + function_stack_top = function_stack_pointer; + + if (log) + log->Printf("-- [UserExpression::Execute] Execution of expression begins --"); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + lldb::ExpressionResults execution_result = + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + if (log) + log->Printf("-- [UserExpression::Execute] Execution of expression completed --"); + + if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) + { + const char *error_desc = NULL; + + if (call_plan_sp) + { + lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); + if (real_stop_info_sp) + error_desc = real_stop_info_sp->GetDescription(); + } + if (error_desc) + error_stream.Printf("Execution was interrupted, reason: %s.", error_desc); + else + error_stream.PutCString("Execution was interrupted."); + + if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || + (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) + error_stream.PutCString( + "\nThe process has been returned to the state before expression evaluation."); + else + { + if (execution_result == lldb::eExpressionHitBreakpoint) + user_expression_plan->TransferExpressionOwnership(); + error_stream.PutCString( + "\nThe process has been left at the point where it was interrupted, " + "use \"thread return -x\" to return to the state before expression evaluation."); + } + + return execution_result; + } + else if (execution_result == lldb::eExpressionStoppedForDebug) + { + error_stream.PutCString( + "Execution was halted at the first instruction of the expression " + "function because \"debug\" was requested.\n" + "Use \"thread return -x\" to return to the state before expression evaluation."); + return execution_result; + } + else if (execution_result != lldb::eExpressionCompleted) + { + error_stream.Printf("Couldn't execute function; result was %s\n", + Process::ExecutionResultAsCString(execution_result)); + return execution_result; + } + } + + if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) + { + return lldb::eExpressionCompleted; + } + else + { + return lldb::eExpressionResultUnavailable; + } + } + else + { + error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); + return lldb::eExpressionSetupError; + } +} + +bool +LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, + lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, + lldb::addr_t function_stack_top) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --"); + + if (!m_dematerializer_sp) + { + error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present"); + return false; + } + + Error dematerialize_error; + + m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom, function_stack_top); + + if (!dematerialize_error.Success()) + { + error_stream.Printf("Couldn't apply expression side effects : %s\n", + dematerialize_error.AsCString("unknown error")); + return false; + } + + result = GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope()); + + if (result) + result->TransferAddress(); + + m_dematerializer_sp.reset(); + + return true; +} + +bool +LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, + lldb::addr_t &struct_address) +{ + lldb::TargetSP target; + lldb::ProcessSP process; + lldb::StackFrameSP frame; + + if (!LockAndCheckContext(exe_ctx, target, process, frame)) + { + error_stream.Printf("The context has changed before we could JIT the expression!\n"); + return false; + } + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) + { + if (m_materialized_address == LLDB_INVALID_ADDRESS) + { + Error alloc_error; + + IRMemoryMap::AllocationPolicy policy = + m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; + + const bool zero_memory = false; + + m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), + m_materializer_ap->GetStructAlignment(), + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + policy, + zero_memory, + alloc_error); + + if (!alloc_error.Success()) + { + error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); + return false; + } + } + + struct_address = m_materialized_address; + + if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) + { + Error alloc_error; + + const size_t stack_frame_size = 512 * 1024; + + const bool zero_memory = false; + + m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, + 8, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyHostOnly, + zero_memory, + alloc_error); + + m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; + + if (!alloc_error.Success()) + { + error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); + return false; + } + } + + Error materialize_error; + + m_dematerializer_sp = + m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); + + if (!materialize_error.Success()) + { + error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + return false; + } + } + return true; +} + +lldb::ModuleSP +LLVMUserExpression::GetJITModule() +{ + if (m_execution_unit_sp) + return m_execution_unit_sp->GetJITModule(); + return lldb::ModuleSP(); +} diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp index ef01feea2a4c..8d68b4f79819 100644 --- a/source/Expression/Materializer.cpp +++ b/source/Expression/Materializer.cpp @@ -7,12 +7,15 @@ // //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Core/Log.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ClangExpressionVariable.h" -#include "lldb/Expression/ClangPersistentVariables.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/Materializer.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" @@ -48,7 +51,7 @@ Materializer::AddStructMember (Entity &entity) } void -Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type) +Materializer::Entity::SetSizeAndAlignmentFromType (CompilerType &type) { m_size = type.GetByteSize(nullptr); @@ -66,9 +69,11 @@ Materializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type) class EntityPersistentVariable : public Materializer::Entity { public: - EntityPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp) : + EntityPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp, + Materializer::PersistentVariableDelegate *delegate) : Entity(), - m_persistent_variable_sp(persistent_variable_sp) + m_persistent_variable_sp(persistent_variable_sp), + m_delegate(delegate) { // Hard-coding to maximum size of a pointer since persistent variables are materialized by reference m_size = 8; @@ -82,11 +87,13 @@ public: // Allocate a spare memory area to store the persistent variable's contents. Error allocate_error; + const bool zero_memory = false; lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(), 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, + zero_memory, allocate_error); if (!allocate_error.Success()) @@ -99,21 +106,21 @@ public: log->Printf("Allocated %s (0x%" PRIx64 ") successfully", m_persistent_variable_sp->GetName().GetCString(), mem); // Put the location of the spare memory into the live data of the ValueObject. - + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(), - m_persistent_variable_sp->GetTypeFromUser(), + m_persistent_variable_sp->GetCompilerType(), m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, - m_persistent_variable_sp->GetByteSize()); + map.GetAddressByteSize()); // Clear the flag if the variable will never be deallocated. - if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget) + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) { Error leak_error; map.Leak(mem, leak_error); - m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation; + m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation; } // Write the contents of the variable to the area. @@ -147,7 +154,10 @@ public: } } - void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) + void Materialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -161,17 +171,17 @@ public: m_persistent_variable_sp->m_flags); } - if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation) + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation) { MakeAllocation(map, err); - m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated; if (!err.Success()) return; } - if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) || - m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) + if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) || + m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) { Error write_error; @@ -192,12 +202,12 @@ public: } } - void Dematerialize (lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) + void Dematerialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -211,10 +221,15 @@ public: m_persistent_variable_sp->m_flags); } - if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) || - (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)) + if (m_delegate) + { + m_delegate->DidDematerialize(m_persistent_variable_sp); + } + + if ((m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsLLDBAllocated) || + (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference)) { - if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVIsProgramReference && !m_persistent_variable_sp->m_live_sp) { // If the reference comes from the program, then the ClangExpressionVariable's @@ -230,9 +245,9 @@ public: err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); return; } - + m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (), - m_persistent_variable_sp->GetTypeFromUser(), + m_persistent_variable_sp.get()->GetCompilerType(), m_persistent_variable_sp->GetName(), location, eAddressTypeLoad, @@ -246,10 +261,10 @@ public: // If the variable is resident in the stack frame created by the expression, // then it cannot be relied upon to stay around. We treat it as needing // reallocation. - m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; - m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; - m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; - m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference; + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVIsLLDBAllocated; + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation; + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry; + m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVIsProgramReference; } } @@ -267,8 +282,8 @@ public: return; } - if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry || - m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget) + if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsFreezeDry || + m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget) { if (log) log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize()); @@ -290,7 +305,7 @@ public: return; } - m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry; + m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsFreezeDry; } } else @@ -305,14 +320,14 @@ public: { // Allocations are not persistent so persistent variables cannot stay materialized. - m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsAllocation; DestroyAllocation(map, err); if (!err.Success()) return; } - else if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation && - !(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)) + else if (m_persistent_variable_sp->m_flags & ExpressionVariable::EVNeedsAllocation && + !(m_persistent_variable_sp->m_flags & ExpressionVariable::EVKeepInTarget)) { DestroyAllocation(map, err); if (!err.Success()) @@ -320,7 +335,7 @@ public: } } - void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; @@ -386,18 +401,22 @@ public: log->PutCString(dump_stream.GetData()); } - void Wipe (IRMemoryMap &map, lldb::addr_t process_address) + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } + private: - lldb::ClangExpressionVariableSP m_persistent_variable_sp; + lldb::ExpressionVariableSP m_persistent_variable_sp; + Materializer::PersistentVariableDelegate *m_delegate; }; uint32_t -Materializer::AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err) +Materializer::AddPersistentVariable (lldb::ExpressionVariableSP &persistent_variable_sp, + PersistentVariableDelegate *delegate, + Error &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityPersistentVariable (persistent_variable_sp)); + iter->reset (new EntityPersistentVariable (persistent_variable_sp, delegate)); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); return ret; @@ -416,10 +435,13 @@ public: // Hard-coding to maximum size of a pointer since all variables are materialized by reference m_size = 8; m_alignment = 8; - m_is_reference = m_variable_sp->GetType()->GetClangForwardType().IsReferenceType(); + m_is_reference = m_variable_sp->GetType()->GetForwardCompilerType ().IsReferenceType(); } - void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) + void Materialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -525,15 +547,22 @@ public: return; } - size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign(); + size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType ().GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; if (!byte_align) byte_align = 1; Error alloc_error; + const bool zero_memory = false; + + m_temporary_allocation = map.Malloc(data.GetByteSize(), + byte_align, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyMirror, + zero_memory, + alloc_error); - m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); m_temporary_allocation_size = data.GetByteSize(); m_original_data.reset(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); @@ -566,12 +595,12 @@ public: } } - void Dematerialize (lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) + void Dematerialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -650,7 +679,7 @@ public: } } - void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; @@ -722,7 +751,7 @@ public: log->PutCString(dump_stream.GetData()); } - void Wipe (IRMemoryMap &map, lldb::addr_t process_address) + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { @@ -735,6 +764,7 @@ public: } } + private: lldb::VariableSP m_variable_sp; bool m_is_reference; @@ -756,20 +786,27 @@ Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err) class EntityResultVariable : public Materializer::Entity { public: - EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) : + EntityResultVariable (const CompilerType &type, + bool is_program_reference, + bool keep_in_memory, + Materializer::PersistentVariableDelegate *delegate) : Entity(), m_type(type), m_is_program_reference(is_program_reference), m_keep_in_memory(keep_in_memory), m_temporary_allocation(LLDB_INVALID_ADDRESS), - m_temporary_allocation_size(0) + m_temporary_allocation_size(0), + m_delegate(delegate) { // Hard-coding to maximum size of a pointer since all results are materialized by reference m_size = 8; m_alignment = 8; } - void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) + void Materialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + Error &err) override { if (!m_is_program_reference) { @@ -789,8 +826,14 @@ public: byte_align = 1; Error alloc_error; - - m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); + const bool zero_memory = true; + + m_temporary_allocation = map.Malloc(byte_size, + byte_align, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyMirror, + zero_memory, + alloc_error); m_temporary_allocation_size = byte_size; if (!alloc_error.Success()) @@ -810,23 +853,12 @@ public: } } - void Dematerialize (lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) - { - err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method"); - } - - void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp, - lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) + void Dematerialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom, + Error &err) override { err.Clear(); @@ -858,15 +890,30 @@ public: return; } - ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName(); + Error type_system_error; + TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage()); + + if (!type_system) + { + err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString()); + return; + } + + PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState(); + + if (!persistent_state) + { + err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables"); + return; + } - lldb::ClangExpressionVariableSP ret; + ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName(); - ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope, - name, - m_type, - map.GetByteOrder(), - map.GetAddressByteSize()); + lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope, + name, + m_type, + map.GetByteOrder(), + map.GetAddressByteSize()); if (!ret) { @@ -876,6 +923,11 @@ public: lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); + if (m_delegate) + { + m_delegate->DidDematerialize(ret); + } + bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); if (can_persist && m_keep_in_memory) @@ -900,12 +952,10 @@ public: err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); return; } - - result_variable_sp = ret; if (!can_persist || !m_keep_in_memory) { - ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + ret->m_flags |= ExpressionVariable::EVNeedsAllocation; if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { @@ -915,14 +965,14 @@ public: } else { - ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; } m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } - void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; @@ -995,7 +1045,7 @@ public: log->PutCString(dump_stream.GetData()); } - void Wipe (IRMemoryMap &map, lldb::addr_t process_address) + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) { @@ -1007,23 +1057,28 @@ public: m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } + private: - TypeFromUser m_type; + CompilerType m_type; bool m_is_program_reference; bool m_keep_in_memory; lldb::addr_t m_temporary_allocation; size_t m_temporary_allocation_size; + Materializer::PersistentVariableDelegate *m_delegate; }; uint32_t -Materializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err) +Materializer::AddResultVariable (const CompilerType &type, + bool is_program_reference, + bool keep_in_memory, + PersistentVariableDelegate *delegate, + Error &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); - iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory)); + iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate)); uint32_t ret = AddStructMember(**iter); (*iter)->SetOffset(ret); - m_result_entity = iter->get(); return ret; } @@ -1039,7 +1094,10 @@ public: m_alignment = 8; } - void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) + void Materialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1083,12 +1141,12 @@ public: } } - void Dematerialize (lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) + void Dematerialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1104,7 +1162,7 @@ public: // no work needs to be done } - void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; @@ -1138,9 +1196,10 @@ public: log->PutCString(dump_stream.GetData()); } - void Wipe (IRMemoryMap &map, lldb::addr_t process_address) + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } + private: Symbol m_symbol; }; @@ -1167,7 +1226,10 @@ public: m_alignment = m_register_info.byte_size; } - void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) + void Materialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1223,12 +1285,12 @@ public: } } - void Dematerialize (lldb::StackFrameSP &frame_sp, - IRMemoryMap &map, - lldb::addr_t process_address, - lldb::addr_t frame_top, - lldb::addr_t frame_bottom, - Error &err) + void Dematerialize(lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom, + Error &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1280,7 +1342,7 @@ public: } } - void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) + void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override { StreamString dump_stream; @@ -1315,9 +1377,10 @@ public: log->PutCString(dump_stream.GetData()); } - void Wipe (IRMemoryMap &map, lldb::addr_t process_address) + void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { } + private: RegisterInfo m_register_info; lldb::DataBufferSP m_register_contents; @@ -1335,7 +1398,6 @@ Materializer::AddRegister (const RegisterInfo ®ister_info, Error &err) Materializer::Materializer () : m_dematerializer_wp(), - m_result_entity(NULL), m_current_offset(0), m_struct_alignment(8) { @@ -1395,7 +1457,9 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb: } void -Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top) +Materializer::Dematerializer::Dematerialize (Error &error, + lldb::addr_t frame_bottom, + lldb::addr_t frame_top) { lldb::StackFrameSP frame_sp; @@ -1428,14 +1492,7 @@ Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpression for (EntityUP &entity_up : m_materializer->m_entities) { - if (entity_up.get() == m_materializer->m_result_entity) - { - static_cast(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); - } - else - { - entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); - } + entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); if (!error.Success()) break; @@ -1456,7 +1513,9 @@ Materializer::Dematerializer::Wipe () entity_up->Wipe (*m_map, m_process_address); } - m_materializer = NULL; - m_map = NULL; + m_materializer = nullptr; + m_map = nullptr; m_process_address = LLDB_INVALID_ADDRESS; } + +Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default; diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp new file mode 100644 index 000000000000..1727a13abd06 --- /dev/null +++ b/source/Expression/REPL.cpp @@ -0,0 +1,649 @@ +//===-- REPL.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Expression/REPL.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/AnsiTerminal.h" + +using namespace lldb_private; + +REPL::REPL(LLVMCastKind kind, Target &target) : + m_target(target), + m_kind(kind) +{ + // Make sure all option values have sane defaults + Debugger &debugger = m_target.GetDebugger(); + CommandInterpreter &ci = debugger.GetCommandInterpreter(); + m_format_options.OptionParsingStarting(ci); + m_varobj_options.OptionParsingStarting(ci); + m_command_options.OptionParsingStarting(ci); + + // Default certain settings for REPL regardless of the global settings. + m_command_options.unwind_on_error = false; + m_command_options.ignore_breakpoints = false; + m_command_options.debug = false; +} + +REPL::~REPL() = default; + +lldb::REPLSP +REPL::Create(Error &err, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options) +{ + uint32_t idx = 0; + lldb::REPLSP ret; + + while (REPLCreateInstance create_instance = PluginManager::GetREPLCreateCallbackAtIndex(idx++)) + { + ret = (*create_instance)(err, language, debugger, target, repl_options); + if (ret) + { + break; + } + } + + return ret; +} + +std::string +REPL::GetSourcePath() +{ + ConstString file_basename = GetSourceFileBasename(); + + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath (lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + 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.AppendPathComponent(file_basename.AsCString()); + } + + return tmpdir_file_spec.GetPath(); +} + +lldb::IOHandlerSP +REPL::GetIOHandler() +{ + if (!m_io_handler_sp) + { + Debugger &debugger = m_target.GetDebugger(); + m_io_handler_sp.reset (new IOHandlerEditline (debugger, + IOHandler::Type::REPL, + "lldb-repl", // Name of input reader for history + "> ", // prompt + ". ", // Continuation prompt + true, // Multi-line + true, // The REPL prompt is always colored + 1, // Line number + *this)); + + // Don't exit if CTRL+C is pressed + static_cast(m_io_handler_sp.get())->SetInterruptExits(false); + + if (m_io_handler_sp->GetIsInteractive() && m_io_handler_sp->GetIsRealTerminal()) + { + m_indent_str.assign (debugger.GetTabSize(), ' '); + m_enable_auto_indent = debugger.GetAutoIndent(); + } + else + { + m_indent_str.clear(); + m_enable_auto_indent = false; + } + + } + return m_io_handler_sp; +} + +void +REPL::IOHandlerActivated (IOHandler &io_handler) +{ + lldb::ProcessSP process_sp = m_target.GetProcessSP(); + if (process_sp && process_sp->IsAlive()) + return; + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + error_sp->Printf("REPL requires a running target process.\n"); + io_handler.SetIsDone(true); +} + +bool +REPL::IOHandlerInterrupt (IOHandler &io_handler) +{ + return false; +} + +void +REPL::IOHandlerInputInterrupted (IOHandler &io_handler, + std::string &line) +{ +} + +const char * +REPL::IOHandlerGetFixIndentationCharacters() +{ + return (m_enable_auto_indent ? GetAutoIndentCharacters() : nullptr); +} + +ConstString +REPL::IOHandlerGetControlSequence (char ch) +{ + if (ch == 'd') + return ConstString(":quit\n"); + return ConstString(); +} + +const char * +REPL::IOHandlerGetCommandPrefix () +{ + return ":"; +} + +const char * +REPL::IOHandlerGetHelpPrologue () +{ + return "\nThe REPL (Read-Eval-Print-Loop) acts like an interpreter. " + "Valid statements, expressions, and declarations are immediately compiled and executed.\n\n" + "The complete set of LLDB debugging commands are also available as described below. Commands " + "must be prefixed with a colon at the REPL prompt (:quit for example.) Typing just a colon " + "followed by return will switch to the LLDB prompt.\n\n"; +} + +bool +REPL::IOHandlerIsInputComplete (IOHandler &io_handler, + StringList &lines) +{ + // Check for meta command + const size_t num_lines = lines.GetSize(); + if (num_lines == 1) + { + const char *first_line = lines.GetStringAtIndex(0); + if (first_line[0] == ':') + return true; // Meta command is a single line where that starts with ':' + } + + // Check if REPL input is done + std::string source_string (lines.CopyList()); + return SourceIsComplete(source_string); +} + +int +REPL::CalculateActualIndentation (const StringList &lines) +{ + std::string last_line = lines[lines.GetSize() - 1]; + + int actual_indent = 0; + for (char &ch : last_line) + { + if (ch != ' ') break; + ++actual_indent; + } + + return actual_indent; +} + +int +REPL::IOHandlerFixIndentation (IOHandler &io_handler, + const StringList &lines, + int cursor_position) +{ + if (!m_enable_auto_indent) return 0; + + if (!lines.GetSize()) + { + return 0; + } + + int tab_size = io_handler.GetDebugger().GetTabSize(); + + lldb::offset_t desired_indent = GetDesiredIndentation(lines, + cursor_position, + tab_size); + + int actual_indent = REPL::CalculateActualIndentation(lines); + + if (desired_indent == LLDB_INVALID_OFFSET) + return 0; + + return (int)desired_indent - actual_indent; +} + +void +REPL::IOHandlerInputComplete (IOHandler &io_handler, std::string &code) +{ + lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + bool extra_line = false; + bool did_quit = false; + + if (code.empty()) + { + m_code.AppendString(""); + static_cast(io_handler).SetBaseLineNumber(m_code.GetSize()+1); + } + else + { + Debugger &debugger = m_target.GetDebugger(); + CommandInterpreter &ci = debugger.GetCommandInterpreter(); + extra_line = ci.GetSpaceReplPrompts(); + + ExecutionContext exe_ctx (m_target.GetProcessSP()->GetThreadList().GetSelectedThread()->GetSelectedFrame().get()); + + lldb::ProcessSP process_sp(exe_ctx.GetProcessSP()); + + if (code[0] == ':') + { + // Meta command + // Strip the ':' + code.erase(0, 1); + if (Args::StripSpaces (code)) + { + // "lldb" was followed by arguments, so just execute the command dump the results + + // Turn off prompt on quit in case the user types ":quit" + const bool saved_prompt_on_quit = ci.GetPromptOnQuit(); + if (saved_prompt_on_quit) + ci.SetPromptOnQuit(false); + + // Execute the command + CommandReturnObject result; + result.SetImmediateOutputStream(output_sp); + result.SetImmediateErrorStream(error_sp); + ci.HandleCommand(code.c_str(), eLazyBoolNo, result); + + if (saved_prompt_on_quit) + ci.SetPromptOnQuit(true); + + if (result.GetStatus() == lldb::eReturnStatusQuit) + { + did_quit = true; + io_handler.SetIsDone(true); + if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) + { + // We typed "quit" or an alias to quit so we need to check if the + // command interpreter is above us and tell it that it is done as well + // so we don't drop back into the command interpreter if we have already + // quit + lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); + if (io_handler_sp) + io_handler_sp->SetIsDone(true); + } + } + } + else + { + // ":" was followed by no arguments, so push the LLDB command prompt + if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::REPL, IOHandler::Type::CommandInterpreter)) + { + // If the user wants to get back to the command interpreter and the + // command interpreter is what launched the REPL, then just let the + // REPL exit and fall back to the command interpreter. + io_handler.SetIsDone(true); + } + else + { + // The REPL wasn't launched the by the command interpreter, it is the + // base IOHandler, so we need to get the command interpreter and + lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); + if (io_handler_sp) + { + io_handler_sp->SetIsDone(false); + debugger.PushIOHandler(ci.GetIOHandler()); + } + } + } + } + else + { + // Unwind any expression we might have been running in case our REPL + // expression crashed and the user was looking around + if (m_dedicated_repl_mode) + { + Thread *thread = exe_ctx.GetThreadPtr(); + if (thread && thread->UnwindInnermostExpression().Success()) + { + thread->SetSelectedFrameByIndex(0, false); + exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + } + } + + const bool colorize_err = error_sp->GetFile().GetIsTerminalWithColors(); + + EvaluateExpressionOptions expr_options; + expr_options.SetCoerceToId(m_varobj_options.use_objc); + expr_options.SetUnwindOnError(m_command_options.unwind_on_error); + expr_options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints); + expr_options.SetKeepInMemory(true); + expr_options.SetUseDynamic(m_varobj_options.use_dynamic); + expr_options.SetTryAllThreads(m_command_options.try_all_threads); + expr_options.SetGenerateDebugInfo(true); + expr_options.SetREPLEnabled (true); + expr_options.SetColorizeErrors(colorize_err); + expr_options.SetPoundLine(m_repl_source_path.c_str(), m_code.GetSize() + 1); + if (m_command_options.timeout > 0) + expr_options.SetTimeoutUsec(m_command_options.timeout); + else + expr_options.SetTimeoutUsec(0); + + expr_options.SetLanguage(GetLanguage()); + + PersistentExpressionState *persistent_state = m_target.GetPersistentExpressionStateForLanguage(GetLanguage()); + + const size_t var_count_before = persistent_state->GetSize(); + + const char *expr_prefix = nullptr; + lldb::ValueObjectSP result_valobj_sp; + Error error; + lldb::ModuleSP jit_module_sp; + lldb::ExpressionResults execution_results = UserExpression::Evaluate (exe_ctx, + expr_options, + code.c_str(), + expr_prefix, + result_valobj_sp, + error, + 0, // Line offset + &jit_module_sp); + + //CommandInterpreter &ci = debugger.GetCommandInterpreter(); + + if (process_sp && process_sp->IsAlive()) + { + bool add_to_code = true; + bool handled = false; + if (result_valobj_sp) + { + lldb::Format format = m_format_options.GetFormat(); + + if (result_valobj_sp->GetError().Success()) + { + handled |= PrintOneVariable(debugger, output_sp, result_valobj_sp); + } + else if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) + { + if (format != lldb::eFormatVoid && debugger.GetNotifyVoid()) + { + error_sp->PutCString("(void)\n"); + handled = true; + } + } + } + + if (debugger.GetPrintDecls()) + { + for (size_t vi = var_count_before, ve = persistent_state->GetSize(); + vi != ve; + ++vi) + { + lldb::ExpressionVariableSP persistent_var_sp = persistent_state->GetVariableAtIndex(vi); + lldb::ValueObjectSP valobj_sp = persistent_var_sp->GetValueObject(); + + PrintOneVariable(debugger, output_sp, valobj_sp, persistent_var_sp.get()); + } + } + + if (!handled) + { + bool useColors = error_sp->GetFile().GetIsTerminalWithColors(); + switch (execution_results) + { + case lldb::eExpressionSetupError: + case lldb::eExpressionParseError: + add_to_code = false; + // Fall through + case lldb::eExpressionDiscarded: + error_sp->Printf("%s\n", error.AsCString()); + break; + + case lldb::eExpressionCompleted: + break; + case lldb::eExpressionInterrupted: + if (useColors) { + error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); + } + error_sp->Printf("Execution interrupted. "); + if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); + error_sp->Printf("Enter code to recover and continue.\nEnter LLDB commands to investigate (type :help for assistance.)\n"); + break; + + case lldb::eExpressionHitBreakpoint: + // Breakpoint was hit, drop into LLDB command interpreter + if (useColors) { + error_sp->Printf(ANSI_ESCAPE1(ANSI_FG_COLOR_RED)); + error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_BOLD)); + } + output_sp->Printf("Execution stopped at breakpoint. "); + if (useColors) error_sp->Printf(ANSI_ESCAPE1(ANSI_CTRL_NORMAL)); + output_sp->Printf("Enter LLDB commands to investigate (type help for assistance.)\n"); + { + lldb::IOHandlerSP io_handler_sp (ci.GetIOHandler()); + if (io_handler_sp) + { + io_handler_sp->SetIsDone(false); + debugger.PushIOHandler(ci.GetIOHandler()); + } + } + break; + + case lldb::eExpressionTimedOut: + error_sp->Printf("error: timeout\n"); + if (error.AsCString()) + error_sp->Printf("error: %s\n", error.AsCString()); + break; + case lldb::eExpressionResultUnavailable: + // Shoulnd't happen??? + error_sp->Printf("error: could not fetch result -- %s\n", error.AsCString()); + break; + case lldb::eExpressionStoppedForDebug: + // Shoulnd't happen??? + error_sp->Printf("error: stopped for debug -- %s\n", error.AsCString()); + break; + } + } + + if (add_to_code) + { + const uint32_t new_default_line = m_code.GetSize() + 1; + + m_code.SplitIntoLines(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); + std::string code (m_code.CopyList()); + code.append(1, '\n'); + size_t bytes_written = code.size(); + file.Write(code.c_str(), bytes_written); + file.Close(); + + // Now set the default file and line to the REPL source file + m_target.GetSourceManager().SetDefaultFileAndLine(FileSpec(m_repl_source_path.c_str(), false), new_default_line); + } + static_cast(io_handler).SetBaseLineNumber(m_code.GetSize()+1); + } + if (extra_line) + { + fprintf(output_sp->GetFile().GetStream(), "\n"); + } + } + } + + // Don't complain about the REPL process going away if we are in the process of quitting. + if (!did_quit && (!process_sp || !process_sp->IsAlive())) + { + error_sp->Printf("error: REPL process is no longer alive, exiting REPL\n"); + io_handler.SetIsDone(true); + } + } +} + +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) +{ + matches.Clear(); + + llvm::StringRef line (current_line, cursor - current_line); + + // Complete an LLDB command if the first character is a colon... + if (!line.empty() && line[0] == ':') + { + Debugger &debugger = m_target.GetDebugger(); + + // auto complete LLDB commands + 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); + } + + // Strip spaces from the line and see if we had only spaces + line = line.ltrim(); + if (line.empty()) + { + // Only spaces on this line, so just indent + matches.AppendString(m_indent_str); + return 1; + } + + std::string current_code; + current_code.append(m_code.CopyList()); + + IOHandlerEditline &editline = static_cast(io_handler); + const StringList *current_lines = editline.GetCurrentLines(); + if (current_lines) + { + const uint32_t current_line_idx = editline.GetCurrentLineIndex(); + + if (current_line_idx < current_lines->GetSize()) + { + for (uint32_t i=0; iGetStringAtIndex(i); + if (line_cstr) + { + current_code.append("\n"); + current_code.append (line_cstr); + } + } + } + } + + if (cursor > current_line) + { + current_code.append("\n"); + current_code.append(current_line, cursor - current_line); + } + + return CompleteCode(current_code, matches); +} + +bool +QuitCommandOverrideCallback(void *baton, const char **argv) +{ + Target *target = (Target *)baton; + lldb::ProcessSP process_sp (target->GetProcessSP()); + if (process_sp) + { + process_sp->Destroy(false); + process_sp->GetTarget().GetDebugger().ClearIOHandlers(); + } + return false; +} + +Error +REPL::RunLoop () +{ + Error error; + + error = DoInitialization(); + m_repl_source_path = GetSourcePath(); + + if (!error.Success()) + return error; + + Debugger &debugger = m_target.GetDebugger(); + + lldb::IOHandlerSP io_handler_sp (GetIOHandler()); + + FileSpec save_default_file; + uint32_t save_default_line = 0; + + if (!m_repl_source_path.empty()) + { + // Save the current default file and line + m_target.GetSourceManager().GetDefaultFileAndLine(save_default_file, save_default_line); + } + + debugger.PushIOHandler(io_handler_sp); + + // Check if we are in dedicated REPL mode where LLDB was start with the "--repl" option + // from the command line. Currently we know this by checking if the debugger already + // has a IOHandler thread. + if (!debugger.HasIOHandlerThread()) + { + // The debugger doesn't have an existing IOHandler thread, so this must be + // dedicated REPL mode... + m_dedicated_repl_mode = true; + debugger.StartIOHandlerThread(); + std::string command_name_str ("quit"); + CommandObject *cmd_obj = debugger.GetCommandInterpreter().GetCommandObjectForCommand(command_name_str); + if (cmd_obj) + { + assert(command_name_str.empty()); + cmd_obj->SetOverrideCallback (QuitCommandOverrideCallback, &m_target); + } + } + + // Wait for the REPL command interpreter to get popped + io_handler_sp->WaitForPop(); + + if (m_dedicated_repl_mode) + { + // If we were in dedicated REPL mode we would have started the + // IOHandler thread, and we should kill our process + lldb::ProcessSP process_sp = m_target.GetProcessSP(); + if (process_sp && process_sp->IsAlive()) + process_sp->Destroy(false); + + // Wait for the IO handler thread to exit (TODO: don't do this if the IO handler thread already exists...) + debugger.JoinIOHandlerThread(); + } + + // Restore the default file and line + if (save_default_file && save_default_line != 0) + m_target.GetSourceManager().SetDefaultFileAndLine(save_default_file, save_default_line); + return error; +} diff --git a/source/Expression/UserExpression.cpp b/source/Expression/UserExpression.cpp new file mode 100644 index 000000000000..70f004ba25c9 --- /dev/null +++ b/source/Expression/UserExpression.cpp @@ -0,0 +1,348 @@ +//===-- UserExpression.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#if HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Expression/UserExpression.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +using namespace lldb_private; + +UserExpression::UserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options) : + Expression(exe_scope), + m_expr_text(expr), + m_expr_prefix(expr_prefix ? expr_prefix : ""), + m_language(language), + m_desired_type(desired_type), + m_options (options) +{ +} + +UserExpression::~UserExpression () +{ +} + +void +UserExpression::InstallContext (ExecutionContext &exe_ctx) +{ + m_jit_process_wp = exe_ctx.GetProcessSP(); + + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + + if (frame_sp) + m_address = frame_sp->GetFrameCodeAddress(); +} + +bool +UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, + lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::StackFrameSP &frame_sp) +{ + lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); + process_sp = exe_ctx.GetProcessSP(); + + if (process_sp != expected_process_sp) + return false; + + process_sp = exe_ctx.GetProcessSP(); + target_sp = exe_ctx.GetTargetSP(); + frame_sp = exe_ctx.GetFrameSP(); + + if (m_address.IsValid()) + { + if (!frame_sp) + return false; + else + return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); + } + + return true; +} + +bool +UserExpression::MatchesContext (ExecutionContext &exe_ctx) +{ + lldb::TargetSP target_sp; + lldb::ProcessSP process_sp; + lldb::StackFrameSP frame_sp; + + return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); +} + +lldb::addr_t +UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp, + ConstString &object_name, + Error &err) +{ + err.Clear(); + + if (!frame_sp) + { + err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + lldb::VariableSP var_sp; + lldb::ValueObjectSP valobj_sp; + + valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), + lldb::eNoDynamicValues, + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsNoFragileObjcIvar | + StackFrame::eExpressionPathOptionsNoSyntheticChildren | + StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, + var_sp, + err); + + if (!err.Success() || !valobj_sp.get()) + return LLDB_INVALID_ADDRESS; + + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (ret == LLDB_INVALID_ADDRESS) + { + err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + return ret; +} + +lldb::ExpressionResults +UserExpression::Evaluate (ExecutionContext &exe_ctx, + const EvaluateExpressionOptions& options, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + Error &error, + uint32_t line_offset, + lldb::ModuleSP *jit_module_sp_ptr) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); + lldb::LanguageType language = options.GetLanguage(); + const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + + Target *target = exe_ctx.GetTargetPtr(); + if (!target) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); + return lldb::eExpressionSetupError; + } + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == NULL || process->GetState() != lldb::eStateStopped) + { + if (execution_policy == eExecutionPolicyAlways) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); + + error.SetErrorString ("expression needed to run but couldn't"); + + return execution_results; + } + } + + if (process == NULL || !process->CanJIT()) + execution_policy = eExecutionPolicyNever; + + const char *full_prefix = NULL; + const char *option_prefix = options.GetPrefix(); + std::string full_prefix_storage; + if (expr_prefix && option_prefix) + { + full_prefix_storage.assign(expr_prefix); + full_prefix_storage.append(option_prefix); + if (!full_prefix_storage.empty()) + full_prefix = full_prefix_storage.c_str(); + } + else if (expr_prefix) + full_prefix = expr_prefix; + else + full_prefix = option_prefix; + + // If the language was not specified in the expression command, + // set it to the language in the target's properties if + // specified, else default to the langage for the frame. + if (language == lldb::eLanguageTypeUnknown) + { + if (target->GetLanguage() != lldb::eLanguageTypeUnknown) + language = target->GetLanguage(); + else if (StackFrame *frame = exe_ctx.GetFramePtr()) + language = frame->GetLanguage(); + } + + lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, + full_prefix, + language, + desired_type, + options, + error)); + if (error.Fail()) + { + if (log) + log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); + return lldb::eExpressionSetupError; + } + + StreamString error_stream; + + if (log) + log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); + + const bool keep_expression_in_memory = true; + const bool generate_debug_info = options.GetGenerateDebugInfo(); + + if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) + { + error.SetErrorString ("expression interrupted by callback before parse"); + result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + return lldb::eExpressionInterrupted; + } + + if (!user_expression_sp->Parse (error_stream, + exe_ctx, + execution_policy, + keep_expression_in_memory, + generate_debug_info)) + { + execution_results = lldb::eExpressionParseError; + if (error_stream.GetString().empty()) + error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); + else + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + } + else + { + // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created + if (jit_module_sp_ptr) + *jit_module_sp_ptr = user_expression_sp->GetJITModule(); + + lldb::ExpressionVariableSP expr_result; + + if (execution_policy == eExecutionPolicyNever && + !user_expression_sp->CanInterpret()) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); + + if (error_stream.GetString().empty()) + error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); + } + else + { + if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) + { + error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); + result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + return lldb::eExpressionInterrupted; + } + + error_stream.GetString().clear(); + + if (log) + log->Printf("== [UserExpression::Evaluate] Executing expression =="); + + execution_results = user_expression_sp->Execute (error_stream, + exe_ctx, + options, + user_expression_sp, + expr_result); + + if (options.GetResultIsInternal() && expr_result && process) + { + process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); + } + + if (execution_results != lldb::eExpressionCompleted) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); + + if (error_stream.GetString().empty()) + error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); + else + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + } + else + { + if (expr_result) + { + result_valobj_sp = expr_result->GetValueObject(); + + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", + result_valobj_sp->GetValueAsCString()); + } + else + { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); + + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); + } + } + } + } + + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) + { + error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); + return lldb::eExpressionInterrupted; + } + + if (result_valobj_sp.get() == NULL) + { + result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + } + + return execution_results; +} diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp new file mode 100644 index 000000000000..f93e358d35df --- /dev/null +++ b/source/Expression/UtilityFunction.cpp @@ -0,0 +1,124 @@ +//===-- ClangUserExpression.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 +#if HAVE_SYS_TYPES_H +# include +#endif + +// C++ Includes + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; +using namespace lldb; + +//------------------------------------------------------------------ +/// Constructor +/// +/// @param[in] text +/// The text of the function. Must be a full translation unit. +/// +/// @param[in] name +/// The name of the function, as used in the text. +//------------------------------------------------------------------ +UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name) : + Expression (exe_scope), + m_execution_unit_sp (), + m_jit_module_wp (), + m_function_text (ExpressionSourceCode::g_expression_prefix), + m_function_name (name) +{ + if (text && text[0]) + m_function_text.append (text); +} + +UtilityFunction::~UtilityFunction () +{ + lldb::ProcessSP process_sp (m_jit_process_wp.lock()); + if (process_sp) + { + lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); + if (jit_module_sp) + process_sp->GetTarget().GetImages().Remove(jit_module_sp); + } + +} + +// FIXME: We should check that every time this is called it is called with the same return type & arguments... + +FunctionCaller * +UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error) +{ + if (m_caller_up) + return m_caller_up.get(); + + ProcessSP process_sp = m_jit_process_wp.lock(); + if (!process_sp) + return nullptr; + + Address impl_code_address; + impl_code_address.SetOffset(StartAddress()); + std::string name(m_function_name); + name.append("-caller"); + + m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(), + return_type, + impl_code_address, + arg_value_list, + name.c_str(), + error)); + if (error.Fail()) + { + + return nullptr; + } + if (m_caller_up) + { + StreamString errors; + errors.Clear(); + unsigned num_errors = m_caller_up->CompileFunction(errors); + if (num_errors) + { + error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".", + m_function_name.c_str(), + errors.GetData()); + m_caller_up.reset(); + return nullptr; + } + + errors.Clear(); + ExecutionContext exe_ctx(process_sp); + + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors)) + { + error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".", + m_function_name.c_str(), + errors.GetData()); + m_caller_up.reset(); + return nullptr; + } + } + return m_caller_up.get(); +} diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp index ed67d0c2c2b3..4640154c6cb1 100644 --- a/source/Host/common/Editline.cpp +++ b/source/Host/common/Editline.cpp @@ -203,7 +203,7 @@ namespace lldb_private { snprintf (history_path, sizeof (history_path), "~/%s-widehistory", m_prefix.c_str()); } - m_path = std::move (FileSpec (history_path, true).GetPath()); + m_path = FileSpec (history_path, true).GetPath(); } if (m_path.empty()) return NULL; @@ -863,34 +863,50 @@ Editline::NextLineCommand (int ch) unsigned char Editline::FixIndentationCommand (int ch) { - if (!m_fix_indentation_callback) + if (!m_fix_indentation_callback) return CC_NORM; - - // Insert the character by hand prior to correction + + // Insert the character typed before proceeding EditLineCharType inserted[] = { (EditLineCharType)ch, 0 }; el_winsertstr (m_editline, inserted); - SaveEditedLine(); - StringList lines = GetInputAsStringList (m_current_line_index + 1); - - // Determine the cursor position LineInfoW * info = const_cast(el_wline (m_editline)); int cursor_position = info->cursor - info->buffer; - + + // Save the edits and determine the correct indentation level + SaveEditedLine(); + StringList lines = GetInputAsStringList (m_current_line_index + 1); int indent_correction = m_fix_indentation_callback (this, lines, cursor_position, m_fix_indentation_callback_baton); - - // Adjust the input buffer to correct indentation + + // If it is already correct no special work is needed + if (indent_correction == 0) + return CC_REFRESH; + + // Change the indentation level of the line + std::string currentLine = lines.GetStringAtIndex (m_current_line_index); if (indent_correction > 0) { - info->cursor = info->buffer; - el_winsertstr (m_editline, EditLineStringType (indent_correction, EditLineCharType(' ')).c_str()); + currentLine = currentLine.insert (0, indent_correction, ' '); } - else if (indent_correction < 0) + else { - info->cursor = info->buffer - indent_correction; - el_wdeletestr (m_editline, -indent_correction); + currentLine = currentLine.erase (0, -indent_correction); } - info->cursor = info->buffer + cursor_position + indent_correction; - return CC_REFRESH; +#if LLDB_EDITLINE_USE_WCHAR + m_input_lines[m_current_line_index] = m_utf8conv.from_bytes (currentLine); +#else + m_input_lines[m_current_line_index] = currentLine; +#endif + + // Update the display to reflect the change + MoveCursor (CursorLocation::EditingCursor, CursorLocation::EditingPrompt); + DisplayInput (m_current_line_index); + + // Reposition the cursor back on the original line and prepare to restart editing + // with a new cursor position + SetCurrentLine (m_current_line_index); + MoveCursor (CursorLocation::BlockEnd, CursorLocation::EditingPrompt); + m_revert_cursor_index = cursor_position + indent_correction; + return CC_NEWLINE; } unsigned char diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index a3420bff65f5..71a6149cd614 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -22,6 +22,8 @@ #include #endif +#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() + #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -143,7 +145,13 @@ File::GetDescriptor() const // Don't open the file descriptor if we don't need to, just get it from the // stream if we have one. if (StreamIsValid()) - return fileno (m_stream); + { +#if defined(LLVM_ON_WIN32) + return _fileno(m_stream); +#else + return fileno(m_stream); +#endif + } // Invalid descriptor and invalid stream, return invalid descriptor. return kInvalidDescriptor; @@ -1045,7 +1053,11 @@ File::CalculateInteractiveAndTerminal () if (::ioctl (fd, TIOCGWINSZ, &window_size) == 0) { if (window_size.ws_col > 0) + { m_is_real_terminal = eLazyBoolYes; + if (llvm::sys::Process::FileDescriptorHasColors(fd)) + m_supports_colors = eLazyBoolYes; + } } } #endif @@ -1068,3 +1080,11 @@ File::GetIsRealTerminal () return m_is_real_terminal == eLazyBoolYes; } +bool +File::GetIsTerminalWithColors () +{ + if (m_supports_colors == eLazyBoolCalculate) + CalculateInteractiveAndTerminal(); + return m_supports_colors == eLazyBoolYes; +} + diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp index ceb094b9ede7..8885a791d88c 100644 --- a/source/Host/common/FileSpec.cpp +++ b/source/Host/common/FileSpec.cpp @@ -107,7 +107,7 @@ FileSpec::ResolveUsername (llvm::SmallVectorImpl &path) return; llvm::StringRef path_str(path.data(), path.size()); - size_t slash_pos = path_str.find_first_of("/", 1); + size_t slash_pos = path_str.find('/', 1); if (slash_pos == 1 || path.size() == 1) { // A path of ~/ resolves to the current user's home dir @@ -789,6 +789,28 @@ FileSpec::GetFileType () const return eFileTypeInvalid; } +bool +FileSpec::IsSymbolicLink () const +{ + char resolved_path[PATH_MAX]; + if (!GetPath (resolved_path, sizeof (resolved_path))) + return false; + +#ifdef _WIN32 + auto attrs = ::GetFileAttributes (resolved_path); + if (attrs == INVALID_FILE_ATTRIBUTES) + return false; + + return (attrs & FILE_ATTRIBUTE_REPARSE_POINT); +#else + struct stat file_stats; + if (::lstat (resolved_path, &file_stats) != 0) + return false; + + return (file_stats.st_mode & S_IFMT) == S_IFLNK; +#endif +} + uint32_t FileSpec::GetPermissions () const { @@ -1409,7 +1431,7 @@ FileSpec::AppendPathComponent(const char *new_path) return; } StreamString stream; - if (m_filename.IsEmpty()) + if (m_filename.IsEmpty() || (m_filename.GetLength() == 1 && m_filename.GetCString()[0] == '.')) stream.Printf("%s/%s", m_directory.GetCString(), new_path); else if (m_directory.IsEmpty()) stream.Printf("%s/%s", m_filename.GetCString(), new_path); diff --git a/source/Host/common/GetOptInc.cpp b/source/Host/common/GetOptInc.cpp new file mode 100644 index 000000000000..7689f36c8154 --- /dev/null +++ b/source/Host/common/GetOptInc.cpp @@ -0,0 +1,473 @@ +#include "lldb/Host/common/GetOptInc.h" + +#if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) || defined(REPLACE_GETOPT_LONG_ONLY) + +// getopt.cpp +#include +#include +#include + +#if defined(REPLACE_GETOPT) +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static const char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* +* Compute the greatest common divisor of a and b. +*/ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +static void pass() {} +#define warnx(a, ...) pass(); + +/* +* Exchange the block from nonopt_start to nonopt_end with the block +* from nonopt_end to opt_end (keeping the same order of arguments +* in each block). +*/ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, +char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end + i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **)nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* +* parse_long_options -- +* Parse long options in argc/argv argument vector. +* Returns -1 if short_too is set and the option does not match long_options. +*/ +static int +parse_long_options(char * const *nargv, const char *options, +const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = const_cast(place); + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } + else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } + else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } + else + return (long_options[match].val); +} + +/* +* getopt_internal -- +* Parse argc/argv argument vector. Called by user level routines. +*/ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, +const struct option *long_options, int *idx, int flags) +{ + const char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1 || optreset) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } + else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } + else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = const_cast(place); + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } + else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +/* +* getopt -- +* Parse argc/argv argument vector. +* +* [eventually this will replace the BSD getopt] +*/ +#if defined(REPLACE_GETOPT) +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif + +/* +* getopt_long -- +* Parse argc/argv argument vector. +*/ +#if defined(REPLACE_GETOPT_LONG) +int +getopt_long(int nargc, char * const *nargv, const char *options, +const struct option *long_options, int *idx) +{ + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} +#endif + +/* +* getopt_long_only -- +* Parse argc/argv argument vector. +*/ +#if defined(REPLACE_GETOPT_LONG_ONLY) +int +getopt_long_only(int nargc, char * const *nargv, const char *options, +const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE | FLAG_LONGONLY)); +} +#endif + +#endif diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp index 94c78a015651..e89f4def478c 100644 --- a/source/Host/common/Host.cpp +++ b/source/Host/common/Host.cpp @@ -143,7 +143,11 @@ private: #endif // __linux__ #ifdef __linux__ +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) +static __thread volatile sig_atomic_t g_usr1_called; +#else static thread_local volatile sig_atomic_t g_usr1_called; +#endif static void SigUsr1Handler (int) @@ -816,8 +820,8 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau #endif const char *tmp_argv[2]; - char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector(); - char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector(); + char * const *argv = const_cast(launch_info.GetArguments().GetConstArgumentVector()); + char * const *envp = const_cast(launch_info.GetEnvironmentEntries().GetConstArgumentVector()); if (argv == NULL) { // posix_spawn gets very unhappy if it doesn't have at least the program @@ -825,7 +829,7 @@ Host::LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &lau // variables don't make it into the child process if "argv == NULL"!!! tmp_argv[0] = exe_path; tmp_argv[1] = NULL; - argv = (char * const*)tmp_argv; + argv = const_cast(tmp_argv); } #if !defined (__APPLE__) diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp index e969e33190eb..0f4324f83dd6 100644 --- a/source/Host/common/HostInfoBase.cpp +++ b/source/Host/common/HostInfoBase.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include @@ -102,7 +103,7 @@ HostInfoBase::GetVendorString() { static std::once_flag g_once_flag; std::call_once(g_once_flag, []() { - g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str()); + g_fields->m_vendor_string = HostInfo::GetArchitecture().GetTriple().getVendorName().str(); }); return g_fields->m_vendor_string; } @@ -306,7 +307,10 @@ HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) FileSpec lldb_file_spec( Host::GetModuleFileSpecForHostAddress(reinterpret_cast(reinterpret_cast(HostInfoBase::GetLLDBPath)))); - + + // 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); + // Remove the filename so that this FileSpec only represents the directory. file_spec.GetDirectory() = lldb_file_spec.GetDirectory(); @@ -341,19 +345,9 @@ HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) { - file_spec.Clear(); - - const char *tmpdir_cstr = getenv("TMPDIR"); - if (tmpdir_cstr == nullptr) - { - tmpdir_cstr = getenv("TMP"); - if (tmpdir_cstr == nullptr) - tmpdir_cstr = getenv("TEMP"); - } - if (!tmpdir_cstr) - return false; - - file_spec = FileSpec(tmpdir_cstr, false); + llvm::SmallVector tmpdir; + llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir); + file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true); return true; } diff --git a/source/Host/common/Mutex.cpp b/source/Host/common/Mutex.cpp index c26467fa0d79..98f5321ad67f 100644 --- a/source/Host/common/Mutex.cpp +++ b/source/Host/common/Mutex.cpp @@ -27,7 +27,7 @@ #endif // Enable extra mutex error checking -#ifdef LLDB_CONFIGURATION_DEBUG +#if 0 // LLDB_CONFIGURATION_DEBUG #define ENABLE_MUTEX_ERROR_CHECKING 1 #include #endif diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp index 818d69bdabdc..7d2f4012bf85 100644 --- a/source/Host/common/NativeProcessProtocol.cpp +++ b/source/Host/common/NativeProcessProtocol.cpp @@ -436,12 +436,6 @@ NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */) // Default implementation does nothing. } -void -NativeProcessProtocol::Terminate () -{ - // Default implementation does nothing. -} - #ifndef __linux__ // These need to be implemented to support lldb-gdb-server on a given platform. Stubs are // provided to make the rest of the code link on non-supported platforms. @@ -449,6 +443,7 @@ NativeProcessProtocol::Terminate () Error NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp) { llvm_unreachable("Platform has no NativeProcessProtocol support"); @@ -457,6 +452,7 @@ NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info, Error NativeProcessProtocol::Attach (lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop, NativeProcessProtocolSP &process_sp) { llvm_unreachable("Platform has no NativeProcessProtocol support"); diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp index a91e764bfe3b..a9784592a738 100644 --- a/source/Host/common/OptionParser.cpp +++ b/source/Host/common/OptionParser.cpp @@ -16,8 +16,10 @@ using namespace lldb_private; void -OptionParser::Prepare() +OptionParser::Prepare(Mutex::Locker &locker) { + static Mutex g_mutex(Mutex::eMutexTypeNormal); + locker.Lock(g_mutex); #ifdef __GLIBC__ optind = 0; #else diff --git a/source/Host/common/Socket.cpp b/source/Host/common/Socket.cpp index f7e93c634a12..91a5e37424e6 100644 --- a/source/Host/common/Socket.cpp +++ b/source/Host/common/Socket.cpp @@ -12,21 +12,16 @@ #include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Host/Config.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" - -#ifdef __ANDROID_NDK__ -#include -#include -#include -#include -#include -#endif +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/common/UDPSocket.h" #ifndef LLDB_DISABLE_POSIX +#include "lldb/Host/posix/DomainSocket.h" + #include #include #include @@ -35,6 +30,23 @@ #include #endif +#ifdef __linux__ +#include "lldb/Host/linux/AbstractSocket.h" +#endif + +#ifdef __ANDROID_NDK__ +#include +#include +#include +#include +#include +#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) +#include +#include +#include +#endif // ANDROID_ARM_BUILD_STATIC || ANDROID_MIPS_BUILD_STATIC +#endif // __ANDROID_NDK__ + using namespace lldb; using namespace lldb_private; @@ -48,48 +60,8 @@ typedef void * get_socket_option_arg_type; const NativeSocket Socket::kInvalidSocketValue = -1; #endif // #if defined(_WIN32) -#ifdef __ANDROID__ -// Android does not have SUN_LEN -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) -#endif -#endif // #ifdef __ANDROID__ - namespace { -NativeSocket CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit) -{ - auto socketType = type; -#ifdef SOCK_CLOEXEC - if (!child_processes_inherit) { - socketType |= SOCK_CLOEXEC; - } -#endif - return ::socket (domain, socketType, protocol); -} - -NativeSocket Accept(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit) -{ -#ifdef SOCK_CLOEXEC - int flags = 0; - if (!child_processes_inherit) { - flags |= SOCK_CLOEXEC; - } - return ::accept4 (sockfd, addr, addrlen, flags); -#else - return ::accept (sockfd, addr, addrlen); -#endif -} - -void SetLastError(Error &error) -{ -#if defined(_WIN32) - error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); -#else - error.SetErrorToErrno(); -#endif -} - bool IsInterrupted() { #if defined(_WIN32) @@ -114,128 +86,84 @@ Socket::~Socket() Close(); } -Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) +std::unique_ptr Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Error &error) { - // Store the result in a unique_ptr in case we error out, the memory will get correctly freed. - std::unique_ptr final_socket; - NativeSocket sock = kInvalidSocketValue; - Error error; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); - if (log) - log->Printf ("Socket::TcpConnect (host/port = %s)", host_and_port.data()); - - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) - return error; - - // Create the socket - sock = CreateSocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, child_processes_inherit); - if (sock == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - // Since they both refer to the same socket descriptor, arbitrarily choose the send socket to - // be the owner. - final_socket.reset(new Socket(sock, ProtocolTcp, true)); - - // Enable local address reuse - final_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); + error.Clear(); - if (inet_pton_result <= 0) + std::unique_ptr socket_up; + switch (protocol) { - struct hostent *host_entry = gethostbyname (host_str.c_str()); - if (host_entry) - host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); - inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) - { - if (inet_pton_result == -1) - SetLastError(error); - else - error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); - - return error; - } + case ProtocolTcp: + socket_up.reset(new TCPSocket(child_processes_inherit, error)); + break; + case ProtocolUdp: + socket_up.reset(new UDPSocket(child_processes_inherit, error)); + break; + case ProtocolUnixDomain: +#ifndef LLDB_DISABLE_POSIX + socket_up.reset(new DomainSocket(child_processes_inherit, error)); +#else + error.SetErrorString("Unix domain sockets are not supported on this platform."); +#endif + break; + case ProtocolUnixAbstract: +#ifdef __linux__ + socket_up.reset(new AbstractSocket(child_processes_inherit, error)); +#else + error.SetErrorString("Abstract domain sockets are not supported on this platform."); +#endif + break; } - if (-1 == ::connect (sock, (const struct sockaddr *)&sa, sizeof(sa))) - { - SetLastError (error); - return error; - } + if (error.Fail()) + socket_up.reset(); - // Keep our TCP packets coming without any delays. - final_socket->SetOption(IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = final_socket.release(); - return error; + return socket_up; } -Error Socket::TcpListen( - llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket, - Predicate* predicate, - int backlog) +Error Socket::TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) { - std::unique_ptr listen_socket; - NativeSocket listen_sock = kInvalidSocketValue; - Error error; + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - const int protocol = IPPROTO_TCP; - listen_sock = ::CreateSocket (family, socktype, protocol, child_processes_inherit); - if (listen_sock == kInvalidSocketValue) - { - SetLastError (error); + Error error; + std::unique_ptr connect_socket(Create(ProtocolTcp, child_processes_inherit, error)); + if (error.Fail()) return error; - } - listen_socket.reset(new Socket(listen_sock, ProtocolTcp, true)); + error = connect_socket->Connect(host_and_port); + if (error.Success()) + socket = connect_socket.release(); - // enable local address reuse - listen_socket->SetOption(SOL_SOCKET, SO_REUSEADDR, 1); + return error; +} +Error +Socket::TcpListen (llvm::StringRef host_and_port, + bool child_processes_inherit, + Socket *&socket, + Predicate* predicate, + int backlog) +{ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("Socket::TcpListen (%s)", host_and_port.data()); + log->Printf ("Socket::%s (%s)", __FUNCTION__, host_and_port.data()); + Error error; std::string host_str; std::string port_str; int32_t port = INT32_MIN; if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) return error; - SocketAddress anyaddr; - if (anyaddr.SetToAnyAddress (family, port)) - { - int err = ::bind (listen_sock, anyaddr, anyaddr.GetLength()); - if (err == -1) - { - SetLastError (error); - return error; - } - - err = ::listen (listen_sock, backlog); - if (err == -1) - { - SetLastError (error); - return error; - } + std::unique_ptr listen_socket(new TCPSocket(child_processes_inherit, error)); + if (error.Fail()) + return error; + error = listen_socket->Listen(host_and_port, backlog); + if (error.Success()) + { // We were asked to listen on port zero which means we // must now read the actual port that was given to us // as port zero is a special code for "find an open port @@ -250,287 +178,77 @@ Error Socket::TcpListen( // another thread in an efficient manor. if (predicate) predicate->SetValue (port, eBroadcastAlways); - socket = listen_socket.release(); } return error; } -Error Socket::BlockingAccept(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&socket) -{ - Error error; - std::string host_str; - std::string port_str; - int32_t port; - if (!DecodeHostAndPort(host_and_port, host_str, port_str, port, &error)) - return error; - - const sa_family_t family = AF_INET; - const int socktype = SOCK_STREAM; - const int protocol = IPPROTO_TCP; - SocketAddress listen_addr; - if (host_str.empty()) - listen_addr.SetToLocalhost(family, port); - else if (host_str.compare("*") == 0) - listen_addr.SetToAnyAddress(family, port); - else - { - if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol)) - { - error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str()); - return error; - } - } - - bool accept_connection = false; - std::unique_ptr accepted_socket; - - // Loop until we are happy with our connection - while (!accept_connection) - { - struct sockaddr_in accept_addr; - ::memset (&accept_addr, 0, sizeof accept_addr); -#if !(defined (__linux__) || defined(_WIN32)) - accept_addr.sin_len = sizeof accept_addr; -#endif - socklen_t accept_addr_len = sizeof accept_addr; - - int sock = Accept (this->GetNativeSocket(), - (struct sockaddr *)&accept_addr, - &accept_addr_len, - child_processes_inherit); - - if (sock == kInvalidSocketValue) - { - SetLastError (error); - break; - } - - bool is_same_addr = true; -#if !(defined(__linux__) || (defined(_WIN32))) - is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); -#endif - if (is_same_addr) - is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr); - - if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) - { - accept_connection = true; - // Since both sockets have the same descriptor, arbitrarily choose the send - // socket to be the owner. - accepted_socket.reset(new Socket(sock, ProtocolTcp, true)); - } - else - { - const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; - ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - accepted_socket.reset(); - } - } - - if (!accepted_socket) - return error; - - // Keep our TCP packets coming without any delays. - accepted_socket->SetOption (IPPROTO_TCP, TCP_NODELAY, 1); - error.Clear(); - socket = accepted_socket.release(); - return error; - -} - Error Socket::UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) { - std::unique_ptr final_send_socket; - std::unique_ptr final_recv_socket; - NativeSocket final_send_fd = kInvalidSocketValue; - NativeSocket final_recv_fd = kInvalidSocketValue; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) - log->Printf ("Socket::UdpConnect (host/port = %s)", host_and_port.data()); + log->Printf ("Socket::%s (host/port = %s)", __FUNCTION__, host_and_port.data()); + return UDPSocket::Connect(host_and_port, child_processes_inherit, send_socket, recv_socket); +} + +Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ Error error; - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, &error)) + std::unique_ptr connect_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); + if (error.Fail()) return error; - // Setup the receiving end of the UDP connection on this localhost - // on port zero. After we bind to port zero we can read the port. - final_recv_fd = ::CreateSocket (AF_INET, SOCK_DGRAM, 0, child_processes_inherit); - if (final_recv_fd == kInvalidSocketValue) - { - // Socket creation failed... - SetLastError (error); - } - else - { - final_recv_socket.reset(new Socket(final_recv_fd, ProtocolUdp, true)); - - // Socket was created, now lets bind to the requested port - SocketAddress addr; - addr.SetToAnyAddress (AF_INET, 0); + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); - if (::bind (final_recv_fd, addr, addr.GetLength()) == -1) - { - // Bind failed... - SetLastError (error); - } - } + return error; +} - assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); +Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + Error error; + std::unique_ptr listen_socket(Create(ProtocolUnixDomain, child_processes_inherit, error)); if (error.Fail()) return error; - // At this point we have setup the receive port, now we need to - // setup the UDP send socket - - struct addrinfo hints; - struct addrinfo *service_info_list = NULL; - - ::memset (&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; - int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list); - if (err != 0) - { - error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", - host_str.c_str(), - port_str.c_str(), - err, - gai_strerror(err)); - return error; - } - - for (struct addrinfo *service_info_ptr = service_info_list; - service_info_ptr != NULL; - service_info_ptr = service_info_ptr->ai_next) - { - final_send_fd = ::CreateSocket (service_info_ptr->ai_family, - service_info_ptr->ai_socktype, - service_info_ptr->ai_protocol, - child_processes_inherit); - - if (final_send_fd != kInvalidSocketValue) - { - final_send_socket.reset(new Socket(final_send_fd, ProtocolUdp, true)); - final_send_socket->m_udp_send_sockaddr = service_info_ptr; - break; - } - else - continue; - } - - :: freeaddrinfo (service_info_list); - - if (final_send_fd == kInvalidSocketValue) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - send_socket = final_send_socket.release(); - recv_socket = final_recv_socket.release(); - error.Clear(); + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } -Error Socket::UnixDomainConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractConnect(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - std::unique_ptr final_socket; - - // Open the socket that was passed in as an option - struct sockaddr_un saddr_un; - int fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (fd == kInvalidSocketValue) - { - SetLastError (error); - return error; - } - - final_socket.reset(new Socket(fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - - if (::connect (fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) - { - SetLastError (error); + std::unique_ptr connect_socket(Create(ProtocolUnixAbstract, child_processes_inherit, error)); + if (error.Fail()) return error; - } - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = connect_socket->Connect(name); + if (error.Success()) + socket = connect_socket.release(); return error; } -Error Socket::UnixDomainAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +Error +Socket::UnixAbstractAccept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) { Error error; -#ifndef LLDB_DISABLE_POSIX - struct sockaddr_un saddr_un; - std::unique_ptr listen_socket; - std::unique_ptr final_socket; - NativeSocket listen_fd = kInvalidSocketValue; - NativeSocket socket_fd = kInvalidSocketValue; - - listen_fd = ::CreateSocket (AF_UNIX, SOCK_STREAM, 0, child_processes_inherit); - if (listen_fd == kInvalidSocketValue) - { - SetLastError (error); + std::unique_ptr listen_socket(Create(ProtocolUnixAbstract,child_processes_inherit, error)); + if (error.Fail()) return error; - } - - listen_socket.reset(new Socket(listen_fd, ProtocolUnixDomain, true)); - - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, name.data(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - saddr_un.sun_len = SUN_LEN (&saddr_un); -#endif - FileSystem::Unlink(FileSpec{name, true}); - bool success = false; - if (::bind (listen_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0) - { - if (::listen (listen_fd, 5) == 0) - { - socket_fd = Accept (listen_fd, NULL, 0, child_processes_inherit); - if (socket_fd > 0) - { - final_socket.reset(new Socket(socket_fd, ProtocolUnixDomain, true)); - success = true; - } - } - } - - if (!success) - { - SetLastError (error); + error = listen_socket->Listen(name, 5); + if (error.Fail()) return error; - } - // We are done with the listen port - listen_socket.reset(); - socket = final_socket.release(); -#else - error.SetErrorString("Unix domain sockets are not supported on this platform."); -#endif + error = listen_socket->Accept(name, child_processes_inherit, socket); return error; } @@ -605,7 +323,7 @@ Error Socket::Read (void *buf, size_t &num_bytes) else num_bytes = bytes_received; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_COMMUNICATION)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); if (log) { log->Printf ("%p Socket::Read() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", @@ -626,17 +344,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) int bytes_sent = 0; do { - if (m_protocol == ProtocolUdp) - { - bytes_sent = ::sendto (m_socket, - static_cast(buf), - num_bytes, - 0, - m_udp_send_sockaddr, - m_udp_send_sockaddr.GetLength()); - } - else - bytes_sent = ::send (m_socket, static_cast(buf), num_bytes, 0); + bytes_sent = Send(buf, num_bytes); } while (bytes_sent < 0 && IsInterrupted ()); if (bytes_sent < 0) @@ -647,7 +355,7 @@ Error Socket::Write (const void *buf, size_t &num_bytes) else num_bytes = bytes_sent; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_HOST)); + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); if (log) { log->Printf ("%p Socket::Write() (socket = %" PRIu64 ", src = %p, src_len = %" PRIu64 ", flags = 0) => %" PRIi64 " (error = %s)", @@ -698,70 +406,84 @@ int Socket::GetOption(int level, int option_name, int &option_value) { get_socket_option_arg_type option_value_p = reinterpret_cast(&option_value); socklen_t option_value_size = sizeof(int); - return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size); + return ::getsockopt(m_socket, level, option_name, option_value_p, &option_value_size); } int Socket::SetOption(int level, int option_name, int option_value) { set_socket_option_arg_type option_value_p = reinterpret_cast(&option_value); - return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); + return ::setsockopt(m_socket, level, option_name, option_value_p, sizeof(option_value)); } -uint16_t Socket::GetLocalPortNumber(const NativeSocket& socket) +size_t Socket::Send(const void *buf, const size_t num_bytes) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; + return ::send (m_socket, static_cast(buf), num_bytes, 0); } -// Return the port number that is being used by the socket. -uint16_t Socket::GetLocalPortNumber() const +void Socket::SetLastError(Error &error) { - return GetLocalPortNumber (m_socket); +#if defined(_WIN32) + error.SetError(::WSAGetLastError(), lldb::eErrorTypeWin32); +#else + error.SetErrorToErrno(); +#endif } -std::string Socket::GetLocalIPAddress () const +NativeSocket +Socket::CreateSocket(const int domain, + const int type, + const int protocol, + bool child_processes_inherit, + Error& error) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); - } - return ""; -} + error.Clear(); + auto socketType = type; +#ifdef SOCK_CLOEXEC + if (!child_processes_inherit) + socketType |= SOCK_CLOEXEC; +#endif + auto sock = ::socket (domain, socketType, protocol); + if (sock == kInvalidSocketValue) + SetLastError(error); -uint16_t Socket::GetRemotePortNumber () const -{ - if (m_socket != kInvalidSocketValue) - { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetPort (); - } - return 0; + return sock; } -std::string Socket::GetRemoteIPAddress () const +NativeSocket +Socket::AcceptSocket(NativeSocket sockfd, + struct sockaddr *addr, + socklen_t *addrlen, + bool child_processes_inherit, + Error& error) { - // We bound to port zero, so we need to figure out which port we actually bound to - if (m_socket != kInvalidSocketValue) + error.Clear(); +#if defined(ANDROID_ARM_BUILD_STATIC) || defined(ANDROID_MIPS_BUILD_STATIC) + // Temporary workaround for statically linking Android lldb-server with the + // latest API. + int fd = syscall(__NR_accept, sockfd, addr, addrlen); + if (fd >= 0 && !child_processes_inherit) { - SocketAddress sock_addr; - socklen_t sock_addr_len = sock_addr.GetMaxLength (); - if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) - return sock_addr.GetIPAddress (); + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1) + return fd; + SetLastError(error); + close(fd); + } + return fd; +#elif defined(SOCK_CLOEXEC) + int flags = 0; + if (!child_processes_inherit) { + flags |= SOCK_CLOEXEC; } - return ""; +#if defined(__NetBSD__) + NativeSocket fd = ::paccept (sockfd, addr, addrlen, nullptr, flags); +#else + NativeSocket fd = ::accept4 (sockfd, addr, addrlen, flags); +#endif +#else + NativeSocket fd = ::accept (sockfd, addr, addrlen); +#endif + if (fd == kInvalidSocketValue) + SetLastError(error); + return fd; } - - diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp index 3ab6cfeec4a0..c8b1687c378e 100644 --- a/source/Host/common/SocketAddress.cpp +++ b/source/Host/common/SocketAddress.cpp @@ -304,8 +304,10 @@ SocketAddress::getaddrinfo (const char *host, *this = service_info_list; result = IsValid (); } - - :: freeaddrinfo (service_info_list); + + if (service_info_list) + ::freeaddrinfo(service_info_list); + return result; } diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp index 2b63f46c02e6..60e1dc6bf995 100644 --- a/source/Host/common/Symbols.cpp +++ b/source/Host/common/Symbols.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/StreamString.h" @@ -37,8 +38,7 @@ int LocateMacOSXFilesUsingDebugSymbols ( const ModuleSpec &module_spec, - FileSpec *out_exec_fspec, // If non-NULL, try and find the executable - FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file + ModuleSpec &return_module_spec ); #else @@ -47,8 +47,7 @@ int LocateMacOSXFilesUsingDebugSymbols ( const ModuleSpec &module_spec, - FileSpec *out_exec_fspec, // If non-NULL, try and find the executable - FileSpec *out_dsym_fspec // If non-NULL try and find the debug symbol file + ModuleSpec &return_module_spec ) { // Cannot find MacOSX files using debug symbols on non MacOSX. return 0; @@ -79,6 +78,7 @@ FileAtPathContainsArchAndUUID (const FileSpec &file_fspec, const ArchSpec *arch, 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(); if (exec_fspec) { @@ -88,6 +88,17 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym // Make sure the module isn't already just a dSYM file... if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) { + 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); + } + } size_t obj_file_path_length = strlen(path); ::strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path) - strlen(path) - 1); ::strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path) - strlen(path) - 1); @@ -99,6 +110,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym 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 @@ -118,6 +133,10 @@ LocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym 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 @@ -154,22 +173,28 @@ LocateExecutableSymbolFileDsym (const ModuleSpec &module_spec) "LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)", exec_fspec ? exec_fspec->GetFilename().AsCString ("") : "", arch ? arch->GetArchitectureName() : "", - (void*)uuid); + (const void*)uuid); FileSpec symbol_fspec; + 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) { // We failed to easily find the dSYM above, so use DebugSymbols - LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec); + LocateMacOSXFilesUsingDebugSymbols (module_spec, dsym_module_spec); } - return symbol_fspec; + else + { + dsym_module_spec.GetSymbolFileSpec() = symbol_fspec; + } + return dsym_module_spec.GetSymbolFileSpec(); } -FileSpec +ModuleSpec Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) { + ModuleSpec result; const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); const ArchSpec *arch = module_spec.GetArchitecturePtr(); const UUID *uuid = module_spec.GetUUIDPtr(); @@ -177,28 +202,31 @@ Symbols::LocateExecutableObjectFile (const ModuleSpec &module_spec) "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", exec_fspec ? exec_fspec->GetFilename().AsCString ("") : "", arch ? arch->GetArchitectureName() : "", - (void*)uuid); + (const void*)uuid); - FileSpec objfile_fspec; ModuleSpecList module_specs; ModuleSpec matched_module_spec; if (exec_fspec && ObjectFile::GetModuleSpecifications(*exec_fspec, 0, 0, module_specs) && module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { - objfile_fspec = exec_fspec; + result.GetFileSpec() = exec_fspec; } else { - LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL); + LocateMacOSXFilesUsingDebugSymbols (module_spec, result); } - return objfile_fspec; + return result; } FileSpec Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) { - const char *symbol_filename = module_spec.GetSymbolFileSpec().GetFilename().AsCString(); + FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec(); + if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists()) + return symbol_file_spec; + + const char *symbol_filename = symbol_file_spec.GetFilename().AsCString(); if (symbol_filename && symbol_filename[0]) { FileSpecList debug_file_search_paths (Target::GetDefaultDebugFileSearchPaths()); @@ -210,8 +238,10 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) // Add current working directory. debug_file_search_paths.AppendIfUnique (FileSpec(".", true)); +#ifndef LLVM_ON_WIN32 // Add /usr/lib/debug directory. debug_file_search_paths.AppendIfUnique (FileSpec("/usr/lib/debug", true)); +#endif // LLVM_ON_WIN32 std::string uuid_str; const UUID &module_uuid = module_spec.GetUUID(); @@ -224,10 +254,6 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) uuid_str = uuid_str + ".debug"; } - // Get directory of our module. Needed to check debug files like this: - // /usr/lib/debug/usr/lib/library.so.debug - std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString(); - size_t num_directories = debug_file_search_paths.GetSize(); for (size_t idx = 0; idx < num_directories; ++idx) { @@ -242,7 +268,11 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec) files.push_back (dirname + "/" + symbol_filename); files.push_back (dirname + "/.debug/" + symbol_filename); files.push_back (dirname + "/.build-id/" + uuid_str); - files.push_back (dirname + module_directory + "/" + symbol_filename); + + // Some debug files may stored in the module directory like this: + // /usr/lib/debug/usr/lib/library.so.debug + if (!file_dir.IsEmpty()) + files.push_back (dirname + file_dir.AsCString() + "/" + symbol_filename); const uint32_t num_files = files.size(); for (size_t idx_file = 0; idx_file < num_files; ++idx_file) diff --git a/source/Host/common/TCPSocket.cpp b/source/Host/common/TCPSocket.cpp new file mode 100644 index 000000000000..b23055ee7d87 --- /dev/null +++ b/source/Host/common/TCPSocket.cpp @@ -0,0 +1,288 @@ +//===-- TcpSocket.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/TCPSocket.h" + +#include "lldb/Core/Log.h" +#include "lldb/Host/Config.h" + +#ifndef LLDB_DISABLE_POSIX +#include +#include +#include +#endif + +using namespace lldb; +using namespace lldb_private; + +namespace { + +const int kDomain = AF_INET; +const int kType = SOCK_STREAM; + +} + +TCPSocket::TCPSocket(NativeSocket socket, bool should_close) + : Socket(socket, ProtocolTcp, should_close) +{ + +} + +TCPSocket::TCPSocket(bool child_processes_inherit, Error &error) + : TCPSocket(CreateSocket(kDomain, kType, IPPROTO_TCP, child_processes_inherit, error), true) +{ +} + + +// Return the port number that is being used by the socket. +uint16_t +TCPSocket::GetLocalPortNumber() const +{ + if (m_socket != kInvalidSocketValue) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort (); + } + return 0; +} + +std::string +TCPSocket::GetLocalIPAddress() const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket != kInvalidSocketValue) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getsockname (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + +uint16_t +TCPSocket::GetRemotePortNumber() const +{ + if (m_socket != kInvalidSocketValue) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetPort (); + } + return 0; +} + +std::string +TCPSocket::GetRemoteIPAddress () const +{ + // We bound to port zero, so we need to figure out which port we actually bound to + if (m_socket != kInvalidSocketValue) + { + SocketAddress sock_addr; + socklen_t sock_addr_len = sock_addr.GetMaxLength (); + if (::getpeername (m_socket, sock_addr, &sock_addr_len) == 0) + return sock_addr.GetIPAddress (); + } + return ""; +} + +Error +TCPSocket::Connect(llvm::StringRef name) +{ + if (m_socket == kInvalidSocketValue) + return Error("Invalid socket"); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); + if (log) + log->Printf ("TCPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); + + Error error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) + return error; + + // Enable local address reuse + SetOptionReuseAddress(); + + struct sockaddr_in sa; + ::memset (&sa, 0, sizeof (sa)); + sa.sin_family = kDomain; + sa.sin_port = htons (port); + + int inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr); + + if (inet_pton_result <= 0) + { + struct hostent *host_entry = gethostbyname (host_str.c_str()); + if (host_entry) + host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); + inet_pton_result = ::inet_pton (kDomain, host_str.c_str(), &sa.sin_addr); + if (inet_pton_result <= 0) + { + if (inet_pton_result == -1) + SetLastError(error); + else + error.SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); + + return error; + } + } + + if (-1 == ::connect (GetNativeSocket(), (const struct sockaddr *)&sa, sizeof(sa))) + { + SetLastError (error); + return error; + } + + // Keep our TCP packets coming without any delays. + SetOptionNoDelay(); + error.Clear(); + return error; +} + +Error +TCPSocket::Listen(llvm::StringRef name, int backlog) +{ + Error error; + + // enable local address reuse + SetOptionReuseAddress(); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("TCPSocket::%s (%s)", __FUNCTION__, name.data()); + + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) + return error; + + SocketAddress bind_addr; + + // Only bind to the loopback address if we are expecting a connection from + // localhost to avoid any firewall issues. + const bool bind_addr_success = (host_str == "127.0.0.1") ? + bind_addr.SetToLocalhost (kDomain, port) : + bind_addr.SetToAnyAddress (kDomain, port); + + if (!bind_addr_success) + { + error.SetErrorString("Failed to bind port"); + return error; + } + + int err = ::bind (GetNativeSocket(), bind_addr, bind_addr.GetLength()); + if (err != -1) + err = ::listen (GetNativeSocket(), backlog); + + if (err == -1) + SetLastError (error); + + return error; +} + +Error +TCPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&conn_socket) +{ + Error error; + std::string host_str; + std::string port_str; + int32_t port; + if (!DecodeHostAndPort(name, host_str, port_str, port, &error)) + return error; + + const sa_family_t family = kDomain; + const int socktype = kType; + const int protocol = IPPROTO_TCP; + SocketAddress listen_addr; + if (host_str.empty()) + listen_addr.SetToLocalhost(family, port); + else if (host_str.compare("*") == 0) + listen_addr.SetToAnyAddress(family, port); + else + { + if (!listen_addr.getaddrinfo(host_str.c_str(), port_str.c_str(), family, socktype, protocol)) + { + error.SetErrorStringWithFormat("unable to resolve hostname '%s'", host_str.c_str()); + return error; + } + } + + bool accept_connection = false; + std::unique_ptr accepted_socket; + + // Loop until we are happy with our connection + while (!accept_connection) + { + struct sockaddr_in accept_addr; + ::memset (&accept_addr, 0, sizeof accept_addr); +#if !(defined (__linux__) || defined(_WIN32)) + accept_addr.sin_len = sizeof accept_addr; +#endif + socklen_t accept_addr_len = sizeof accept_addr; + + int sock = AcceptSocket (GetNativeSocket(), + (struct sockaddr *)&accept_addr, + &accept_addr_len, + child_processes_inherit, + error); + + if (error.Fail()) + break; + + bool is_same_addr = true; +#if !(defined(__linux__) || (defined(_WIN32))) + is_same_addr = (accept_addr_len == listen_addr.sockaddr_in().sin_len); +#endif + if (is_same_addr) + is_same_addr = (accept_addr.sin_addr.s_addr == listen_addr.sockaddr_in().sin_addr.s_addr); + + if (is_same_addr || (listen_addr.sockaddr_in().sin_addr.s_addr == INADDR_ANY)) + { + accept_connection = true; + accepted_socket.reset(new TCPSocket(sock, true)); + } + else + { + const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; + const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sockaddr_in().sin_addr.s_addr; + ::fprintf (stderr, "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + accepted_socket.reset(); + } + } + + if (!accepted_socket) + return error; + + // Keep our TCP packets coming without any delays. + accepted_socket->SetOptionNoDelay(); + error.Clear(); + conn_socket = accepted_socket.release(); + return error; +} + +int +TCPSocket::SetOptionNoDelay() +{ + return SetOption (IPPROTO_TCP, TCP_NODELAY, 1); +} + +int +TCPSocket::SetOptionReuseAddress() +{ + return SetOption(SOL_SOCKET, SO_REUSEADDR, 1); +} diff --git a/source/Host/common/ThisThread.cpp b/source/Host/common/ThisThread.cpp index 289ec780e9fb..763701441c1a 100644 --- a/source/Host/common/ThisThread.cpp +++ b/source/Host/common/ThisThread.cpp @@ -37,7 +37,7 @@ ThisThread::SetName(llvm::StringRef name, int max_length) { // We're still too long. Since this is a dotted component, use everything after the last // dot, up to a maximum of |length| characters. - std::string::size_type last_dot = truncated_name.find_last_of("."); + std::string::size_type last_dot = truncated_name.rfind('.'); if (last_dot != std::string::npos) begin = last_dot + 1; diff --git a/source/Host/common/UDPSocket.cpp b/source/Host/common/UDPSocket.cpp new file mode 100644 index 000000000000..8297232ae723 --- /dev/null +++ b/source/Host/common/UDPSocket.cpp @@ -0,0 +1,158 @@ +//===-- UdpSocket.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/UDPSocket.h" + +#include "lldb/Core/Log.h" +#include "lldb/Host/Config.h" + +#ifndef LLDB_DISABLE_POSIX +#include +#include +#endif + +#include + +using namespace lldb; +using namespace lldb_private; + +namespace { + +const int kDomain = AF_INET; +const int kType = SOCK_DGRAM; + +const Error kNotSupported("Not supported"); + +} + +UDPSocket::UDPSocket(NativeSocket socket) + : Socket(socket, ProtocolUdp, true) +{ +} + +UDPSocket::UDPSocket(bool child_processes_inherit, Error &error) + : UDPSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) +{ +} + +size_t +UDPSocket::Send(const void *buf, const size_t num_bytes) +{ + return ::sendto (m_socket, + static_cast(buf), + num_bytes, + 0, + m_send_sockaddr, + m_send_sockaddr.GetLength()); +} + +Error +UDPSocket::Connect(llvm::StringRef name) +{ + return kNotSupported; +} + +Error +UDPSocket::Listen(llvm::StringRef name, int backlog) +{ + return kNotSupported; +} + +Error +UDPSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + return kNotSupported; +} + +Error +UDPSocket::Connect(llvm::StringRef name, bool child_processes_inherit, Socket *&send_socket, Socket *&recv_socket) +{ + std::unique_ptr final_send_socket; + std::unique_ptr final_recv_socket; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("UDPSocket::%s (host/port = %s)", __FUNCTION__, name.data()); + + Error error; + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + if (!DecodeHostAndPort (name, host_str, port_str, port, &error)) + return error; + + // Setup the receiving end of the UDP connection on this localhost + // on port zero. After we bind to port zero we can read the port. + final_recv_socket.reset(new UDPSocket(child_processes_inherit, error)); + if (error.Success()) + { + // Socket was created, now lets bind to the requested port + SocketAddress addr; + addr.SetToAnyAddress (AF_INET, 0); + + if (::bind (final_recv_socket->GetNativeSocket(), addr, addr.GetLength()) == -1) + { + // Bind failed... + SetLastError (error); + } + } + + assert(error.Fail() == !(final_recv_socket && final_recv_socket->IsValid())); + if (error.Fail()) + return error; + + // At this point we have setup the receive port, now we need to + // setup the UDP send socket + + struct addrinfo hints; + struct addrinfo *service_info_list = nullptr; + + ::memset (&hints, 0, sizeof(hints)); + hints.ai_family = kDomain; + hints.ai_socktype = kType; + int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list); + if (err != 0) + { + error.SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", + host_str.c_str(), + port_str.c_str(), + err, + gai_strerror(err)); + return error; + } + + for (struct addrinfo *service_info_ptr = service_info_list; + service_info_ptr != nullptr; + service_info_ptr = service_info_ptr->ai_next) + { + auto send_fd = CreateSocket (service_info_ptr->ai_family, + service_info_ptr->ai_socktype, + service_info_ptr->ai_protocol, + child_processes_inherit, + error); + if (error.Success()) + { + final_send_socket.reset(new UDPSocket(send_fd)); + final_send_socket->m_send_sockaddr = service_info_ptr; + break; + } + else + continue; + } + + :: freeaddrinfo (service_info_list); + + if (!final_send_socket) + return error; + + send_socket = final_send_socket.release(); + recv_socket = final_recv_socket.release(); + error.Clear(); + return error; +} diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp index 14e786ab8b16..dc9cb0bc5a33 100644 --- a/source/Host/common/XML.cpp +++ b/source/Host/common/XML.cpp @@ -329,7 +329,7 @@ XMLNode::ForEachSiblingElementWithName (const char *name, NodeCallback const &ca else { if (node->name) - continue; // nullptr name specified and this elemnt has a name, ignore this one + continue; // nullptr name specified and this element has a name, ignore this one } if (callback(XMLNode(node)) == false) @@ -592,7 +592,7 @@ ApplePropertyList::ExtractStringFromValueNode (const XMLNode &node, std::string if (element_name == "true" || element_name == "false") { // The text value _is_ the element name itself... - value = std::move(element_name.str()); + value = element_name.str(); return true; } else if (element_name == "dict" || element_name == "array") @@ -689,5 +689,3 @@ ApplePropertyList::GetStructuredData() #endif return root_sp; } - - diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp index 7f8d7ae96e7a..cf53cda40b19 100644 --- a/source/Host/freebsd/Host.cpp +++ b/source/Host/freebsd/Host.cpp @@ -76,7 +76,7 @@ GetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, size_t arg_data_size = sizeof(arg_data); if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) { - DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); + DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); lldb::offset_t offset = 0; const char *cstr; diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp new file mode 100644 index 000000000000..874285072049 --- /dev/null +++ b/source/Host/netbsd/Host.cpp @@ -0,0 +1,287 @@ +//===-- source/Host/netbsd/Host.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 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Error.h" +#include "lldb/Host/Endian.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Platform.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/NameMatches.h" + +#include "llvm/Support/Host.h" + +extern "C" { + extern char **environ; +} + +using namespace lldb; +using namespace lldb_private; + +size_t +Host::GetEnvironment (StringList &env) +{ + char *v; + char **var = environ; + for (; var != NULL && *var != NULL; ++var) + { + v = ::strchr(*var, (int)'-'); + if (v == NULL) + continue; + env.AppendString(v); + } + return env.GetSize(); +} + +static bool +GetNetBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr, + ProcessInstanceInfo &process_info) +{ + if (!process_info.ProcessIDIsValid()) + return false; + + int pid = process_info.GetProcessID(); + + int mib[4] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV }; + + char arg_data[8192]; + size_t arg_data_size = sizeof(arg_data); + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) != 0) + return false; + + DataExtractor data (arg_data, arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); + lldb::offset_t offset = 0; + const char *cstr; + + cstr = data.GetCStr (&offset); + if (!cstr) + return false; + + process_info.GetExecutableFile().SetFile(cstr, false); + + if (!(match_info_ptr == NULL || + NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), + match_info_ptr->GetNameMatchType(), + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) + { + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) + { + ++offset; + p = data.PeekData(offset, 1); + } + if (p == NULL || offset >= arg_data_size) + break; + + cstr = data.GetCStr(&offset); + if (!cstr) + break; + + proc_args.AppendArgument(cstr); + } + + return true; +} + +static bool +GetNetBSDProcessCPUType (ProcessInstanceInfo &process_info) +{ + if (process_info.ProcessIDIsValid()) + { + process_info.GetArchitecture() = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + return true; + } + process_info.GetArchitecture().Clear(); + return false; +} + +static bool +GetNetBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) +{ + ::kvm_t *kdp; + char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ + + struct ::kinfo_proc2 *proc_kinfo; + const int pid = process_info.GetProcessID(); + int nproc; + + if (!process_info.ProcessIDIsValid()) + goto error; + + if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) + goto error; + + if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_PID, pid, + sizeof(struct ::kinfo_proc2), + &nproc)) == NULL) { + ::kvm_close(kdp); + goto error; + } + + if (nproc < 1) { + ::kvm_close(kdp); /* XXX: we don't check for error here */ + goto error; + } + + process_info.SetParentProcessID (proc_kinfo->p_ppid); + process_info.SetUserID (proc_kinfo->p_ruid); + process_info.SetGroupID (proc_kinfo->p_rgid); + process_info.SetEffectiveUserID (proc_kinfo->p_uid); + process_info.SetEffectiveGroupID (proc_kinfo->p_gid); + + ::kvm_close(kdp); /* XXX: we don't check for error here */ + + return true; + +error: + process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID); + process_info.SetUserID (UINT32_MAX); + process_info.SetGroupID (UINT32_MAX); + process_info.SetEffectiveUserID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); + return false; +} + +uint32_t +Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) +{ + const ::pid_t our_pid = ::getpid(); + const ::uid_t our_uid = ::getuid(); + + const bool all_users = match_info.GetMatchAllUsers() || + // Special case, if lldb is being run as root we can attach to anything + (our_uid == 0); + + kvm_t *kdp; + char errbuf[_POSIX2_LINE_MAX]; /* XXX: error string unused */ + if ((kdp = ::kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) + return 0; + + struct ::kinfo_proc2 *proc_kinfo; + int nproc; + if ((proc_kinfo = ::kvm_getproc2(kdp, KERN_PROC_ALL, 0, + sizeof(struct ::kinfo_proc2), + &nproc)) == NULL) { + ::kvm_close(kdp); + return 0; + } + + for (int i = 0; i < nproc; i++) { + if (proc_kinfo[i].p_pid < 1) + continue; /* not valid */ + /* Make sure the user is acceptable */ + if (!all_users && proc_kinfo[i].p_ruid != our_uid) + continue; + + if (proc_kinfo[i].p_pid == our_pid || // Skip this process + proc_kinfo[i].p_pid == 0 || // Skip kernel (kernel pid is 0) + proc_kinfo[i].p_stat == LSZOMB || // Zombies are bad + proc_kinfo[i].p_flag & P_TRACED || // Being debugged? + proc_kinfo[i].p_flag & P_WEXIT) // Working on exiting + continue; + + + // Every thread is a process in NetBSD, but all the threads of a single + // process have the same pid. Do not store the process info in the + // result list if a process with given identifier is already registered + // there. + if (proc_kinfo[i].p_nlwps > 1) { + bool already_registered = false; + for (size_t pi = 0; pi < process_infos.GetSize(); pi++) { + if (process_infos.GetProcessIDAtIndex(pi) == + proc_kinfo[i].p_pid) { + already_registered = true; + break; + } + } + + if (already_registered) + continue; + } + ProcessInstanceInfo process_info; + process_info.SetProcessID (proc_kinfo[i].p_pid); + process_info.SetParentProcessID (proc_kinfo[i].p_ppid); + process_info.SetUserID (proc_kinfo[i].p_ruid); + process_info.SetGroupID (proc_kinfo[i].p_rgid); + process_info.SetEffectiveUserID (proc_kinfo[i].p_uid); + process_info.SetEffectiveGroupID (proc_kinfo[i].p_gid); + // Make sure our info matches before we go fetch the name and cpu type + if (match_info.Matches (process_info) && + GetNetBSDProcessArgs (&match_info, process_info)) + { + GetNetBSDProcessCPUType (process_info); + if (match_info.Matches (process_info)) + process_infos.Append (process_info); + } + } + + kvm_close(kdp); /* XXX: we don't check for error here */ + + return process_infos.GetSize(); +} + +bool +Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) +{ + process_info.SetProcessID(pid); + + if (GetNetBSDProcessArgs(NULL, process_info)) + { + GetNetBSDProcessCPUType(process_info); + GetNetBSDProcessUserAndGroup(process_info); + return true; + } + + process_info.Clear(); + return false; +} + +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + return lldb::DataBufferSP(); +} + +Error +Host::ShellExpandArguments (ProcessLaunchInfo &launch_info) +{ + return Error("unimplemented"); +} diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp new file mode 100644 index 000000000000..aadda767fdae --- /dev/null +++ b/source/Host/netbsd/HostInfoNetBSD.cpp @@ -0,0 +1,112 @@ +//===-- HostInfoNetBSD.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/netbsd/HostInfoNetBSD.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace lldb_private; + +uint32_t +HostInfoNetBSD::GetMaxThreadNameLength() +{ + return PTHREAD_MAX_NAMELEN_NP; +} + +bool +HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) +{ + struct utsname un; + + ::memset(&un, 0, sizeof(un)); + if (::uname(&un) < 0) + return false; + + /* Accept versions like 7.99.21 and 6.1_STABLE */ + int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major, &minor, &update); + switch(status) { + case 0: + return false; + case 1: + minor = 0; + /* FALLTHROUGH */ + case 2: + update = 0; + /* FALLTHROUGH */ + case 3: + default: + return true; + } +} + +bool +HostInfoNetBSD::GetOSBuildString(std::string &s) +{ + int mib[2] = {CTL_KERN, KERN_OSREV}; + char osrev_str[12]; + int osrev = 0; + size_t osrev_len = sizeof(osrev); + + if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) + { + ::snprintf(osrev_str, sizeof(osrev_str), "%-10.10d", osrev); + s.assign(osrev_str); + return true; + } + + s.clear(); + return false; +} + +bool +HostInfoNetBSD::GetOSKernelDescription(std::string &s) +{ + struct utsname un; + + ::memset(&un, 0, sizeof(un)); + s.clear(); + + if (::uname(&un) < 0) + return false; + + s.assign(un.version); + + return true; +} + +FileSpec +HostInfoNetBSD::GetProgramFileSpec() +{ + static FileSpec g_program_filespec; + + if (!g_program_filespec) + { + ssize_t len; + static char buf[PATH_MAX]; + char name[PATH_MAX]; + + ::snprintf(name, PATH_MAX, "/proc/%d/exe", ::getpid()); + len = ::readlink(name, buf, PATH_MAX - 1); + if (len != -1) + { + buf[len] = '\0'; + g_program_filespec.SetFile(buf, false); + } + } + return g_program_filespec; +} diff --git a/source/Host/netbsd/HostThreadNetBSD.cpp b/source/Host/netbsd/HostThreadNetBSD.cpp new file mode 100644 index 000000000000..06bc502516a6 --- /dev/null +++ b/source/Host/netbsd/HostThreadNetBSD.cpp @@ -0,0 +1,50 @@ +//===-- HostThreadNetBSD.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// lldb Includes +#include "lldb/Host/netbsd/HostThreadNetBSD.h" +#include "lldb/Host/Host.h" + +// C includes +#include +#include +#include +#include +#include +#include + +// C++ includes +#include + +using namespace lldb_private; + +HostThreadNetBSD::HostThreadNetBSD() +{ +} + +HostThreadNetBSD::HostThreadNetBSD(lldb::thread_t thread) + : HostThreadPosix(thread) +{ +} + +void +HostThreadNetBSD::SetName(lldb::thread_t thread, llvm::StringRef &name) +{ + ::pthread_setname_np(thread, "%s", const_cast(name.data())); +} + +void +HostThreadNetBSD::GetName(lldb::thread_t thread, llvm::SmallVectorImpl &name) +{ + char buf[PTHREAD_MAX_NAMELEN_NP]; + ::pthread_getname_np(thread, buf, PTHREAD_MAX_NAMELEN_NP); + + name.clear(); + name.append(buf, buf + strlen(buf)); +} diff --git a/source/Host/netbsd/ThisThread.cpp b/source/Host/netbsd/ThisThread.cpp new file mode 100644 index 000000000000..dff5d9e0f109 --- /dev/null +++ b/source/Host/netbsd/ThisThread.cpp @@ -0,0 +1,30 @@ +//===-- ThisThread.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/ThisThread.h" + +#include "llvm/ADT/SmallVector.h" + +#include +#include + +using namespace lldb_private; + +void +ThisThread::SetName(llvm::StringRef name) +{ + HostNativeThread::SetName(::pthread_self(), name); +} + +void +ThisThread::GetName(llvm::SmallVectorImpl &name) +{ + HostNativeThread::GetName(::pthread_self(), name); +} diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp index f12f98c30b44..dbbd5a1dcc3c 100644 --- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -33,6 +33,8 @@ #endif // C++ Includes +#include + // Other libraries and framework includes #include "llvm/Support/ErrorHandling.h" #if defined(__APPLE__) @@ -45,11 +47,37 @@ #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/common/TCPSocket.h" #include "lldb/Interpreter/Args.h" using namespace lldb; using namespace lldb_private; +const char* ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; +const char* ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; +const char* ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; +const char* ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; +const char* ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; +const char* ConnectionFileDescriptor::UDP_SCHEME = "udp"; +const char* ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; +const char* ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect"; +const char* ConnectionFileDescriptor::FD_SCHEME = "fd"; +const char* ConnectionFileDescriptor::FILE_SCHEME = "file"; + +namespace { + +const char* +GetURLAddress(const char *url, const char *scheme) +{ + const auto prefix = std::string(scheme) + "://"; + if (strstr(url, prefix.c_str()) != url) + return nullptr; + + return url + prefix.size(); +} + +} + ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) : Connection() , m_pipe() @@ -151,49 +179,51 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) if (s && s[0]) { - if (strstr(s, "listen://") == s) + const char *addr = nullptr; + if ((addr = GetURLAddress(s, LISTEN_SCHEME))) { // listen://HOST:PORT - return SocketListenAndAccept(s + strlen("listen://"), error_ptr); + return SocketListenAndAccept(addr, error_ptr); } - else if (strstr(s, "accept://") == s) + else if ((addr = GetURLAddress(s, ACCEPT_SCHEME))) { // unix://SOCKNAME - return NamedSocketAccept(s + strlen("accept://"), error_ptr); + return NamedSocketAccept(addr, error_ptr); } - else if (strstr(s, "unix-accept://") == s) + else if ((addr = GetURLAddress(s, UNIX_ACCEPT_SCHEME))) { // unix://SOCKNAME - return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr); + return NamedSocketAccept(addr, error_ptr); + } + else if ((addr = GetURLAddress(s, CONNECT_SCHEME))) + { + return ConnectTCP(addr, error_ptr); } - else if (strstr(s, "adb://") == s) + else if ((addr = GetURLAddress(s, TCP_CONNECT_SCHEME))) { - int port = -1; - sscanf(s, "adb://%*[^:]:%d", &port); - char host_and_port[sizeof("localhost:65535")]; - snprintf(host_and_port, sizeof(host_and_port), "localhost:%d", port); - return ConnectTCP(host_and_port, error_ptr); + return ConnectTCP(addr, error_ptr); } - else if (strstr(s, "connect://") == s) + else if ((addr = GetURLAddress(s, UDP_SCHEME))) { - return ConnectTCP(s + strlen("connect://"), error_ptr); + return ConnectUDP(addr, error_ptr); } - else if (strstr(s, "tcp-connect://") == s) + else if ((addr = GetURLAddress(s, UNIX_CONNECT_SCHEME))) { - return ConnectTCP(s + strlen("tcp-connect://"), error_ptr); + // unix-connect://SOCKNAME + return NamedSocketConnect(addr, error_ptr); } - else if (strstr(s, "udp://") == s) + else if ((addr = GetURLAddress(s, UNIX_ABSTRACT_CONNECT_SCHEME))) { - return ConnectUDP(s + strlen("udp://"), error_ptr); + // unix-abstract-connect://SOCKNAME + return UnixAbstractSocketConnect(addr, error_ptr); } #ifndef LLDB_DISABLE_POSIX - else if (strstr(s, "fd://") == s) + else if ((addr = GetURLAddress(s, FD_SCHEME))) { // Just passing a native file descriptor within this current process // that is already opened (possibly from a service or other source). - s += strlen("fd://"); bool success = false; - int fd = StringConvert::ToSInt32(s, -1, 0, &success); + int fd = StringConvert::ToSInt32(addr, -1, 0, &success); if (success) { @@ -223,8 +253,8 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) // allow us to specify this. For now, we assume we must // assume we don't own it. - std::unique_ptr tcp_socket; - tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false)); + std::unique_ptr tcp_socket; + tcp_socket.reset(new TCPSocket(fd, false)); // Try and get a socket option from this file descriptor to // see if this is a socket and set m_is_socket accordingly. int resuse; @@ -239,21 +269,21 @@ ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); } - m_uri.assign(s); + m_uri.assign(addr); return eConnectionStatusSuccess; } } if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s); + error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", s); m_read_sp.reset(); m_write_sp.reset(); return eConnectionStatusError; } - else if (strstr(s, "file://") == s) + else if ((addr = GetURLAddress(s, FILE_SCHEME))) { // file:///PATH - const char *path = s + strlen("file://"); + const char *path = addr; int fd = -1; do { @@ -763,6 +793,23 @@ ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *err return eConnectionStatusSuccess; } +lldb::ConnectionStatus +ConnectionFileDescriptor::UnixAbstractSocketConnect(const char *socket_name, Error *error_ptr) +{ + Socket *socket = nullptr; + Error error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket); + if (error_ptr) + *error_ptr = error; + m_write_sp.reset(socket); + m_read_sp = m_write_sp; + if (error.Fail()) + { + return eConnectionStatusError; + } + m_uri.assign(socket_name); + return eConnectionStatusSuccess; +} + ConnectionStatus ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) { @@ -780,7 +827,7 @@ ConnectionFileDescriptor::SocketListenAndAccept(const char *s, Error *error_ptr) listening_socket_up.reset(socket); socket = nullptr; - error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket); + error = listening_socket_up->Accept(s, m_child_processes_inherit, socket); listening_socket_up.reset(); if (error_ptr) *error_ptr = error; @@ -856,9 +903,12 @@ ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) void ConnectionFileDescriptor::InitializeSocket(Socket* socket) { + assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); + TCPSocket* tcp_socket = static_cast(socket); + m_write_sp.reset(socket); m_read_sp = m_write_sp; StreamString strm; - strm.Printf("connect://%s:%u",socket->GetRemoteIPAddress().c_str(), socket->GetRemotePortNumber()); + strm.Printf("connect://%s:%u",tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber()); m_uri.swap(strm.GetString()); } diff --git a/source/Host/posix/DomainSocket.cpp b/source/Host/posix/DomainSocket.cpp new file mode 100644 index 000000000000..b4427e305f3e --- /dev/null +++ b/source/Host/posix/DomainSocket.cpp @@ -0,0 +1,133 @@ +//===-- DomainSocket.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/posix/DomainSocket.h" + +#include "lldb/Host/FileSystem.h" + +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; + +#ifdef __ANDROID__ +// Android does not have SUN_LEN +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path)) +#endif +#endif // #ifdef __ANDROID__ + +namespace { + +const int kDomain = AF_UNIX; +const int kType = SOCK_STREAM; + +bool SetSockAddr(llvm::StringRef name, + const size_t name_offset, + sockaddr_un* saddr_un, + socklen_t& saddr_un_len) +{ + if (name.size() + name_offset > sizeof(saddr_un->sun_path)) + return false; + + memset(saddr_un, 0, sizeof(*saddr_un)); + saddr_un->sun_family = kDomain; + + memcpy(saddr_un->sun_path + name_offset, name.data(), name.size()); + + // For domain sockets we can use SUN_LEN in order to calculate size of + // sockaddr_un, but for abstract sockets we have to calculate size manually + // because of leading null symbol. + if (name_offset == 0) + saddr_un_len = SUN_LEN(saddr_un); + else + saddr_un_len = offsetof(struct sockaddr_un, sun_path) + name_offset + name.size(); + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) + saddr_un->sun_len = saddr_un_len; +#endif + + return true; +} + +} + +DomainSocket::DomainSocket(NativeSocket socket) + : Socket(socket, ProtocolUnixDomain, true) +{ +} + +DomainSocket::DomainSocket(bool child_processes_inherit, Error &error) + : DomainSocket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error)) +{ +} + +DomainSocket::DomainSocket(SocketProtocol protocol, bool child_processes_inherit, Error &error) + : Socket(CreateSocket(kDomain, kType, 0, child_processes_inherit, error), protocol, true) +{ +} + +Error +DomainSocket::Connect(llvm::StringRef name) +{ + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); + + Error error; + if (::connect(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) < 0) + SetLastError (error); + + return error; +} + +Error +DomainSocket::Listen(llvm::StringRef name, int backlog) +{ + sockaddr_un saddr_un; + socklen_t saddr_un_len; + if (!SetSockAddr(name, GetNameOffset(), &saddr_un, saddr_un_len)) + return Error("Failed to set socket address"); + + DeleteSocketFile(name); + + Error error; + if (::bind(GetNativeSocket(), (struct sockaddr *)&saddr_un, saddr_un_len) == 0) + if (::listen(GetNativeSocket(), backlog) == 0) + return error; + + SetLastError(error); + return error; +} + +Error +DomainSocket::Accept(llvm::StringRef name, bool child_processes_inherit, Socket *&socket) +{ + Error error; + auto conn_fd = AcceptSocket(GetNativeSocket(), nullptr, nullptr, child_processes_inherit, error); + if (error.Success()) + socket = new DomainSocket(conn_fd); + + return error; +} + +size_t +DomainSocket::GetNameOffset() const +{ + return 0; +} + +void +DomainSocket::DeleteSocketFile(llvm::StringRef name) +{ + FileSystem::Unlink(FileSpec{name, true}); +} diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp index 52698039b46e..1f2e7db0e1e4 100644 --- a/source/Host/posix/FileSystem.cpp +++ b/source/Host/posix/FileSystem.cpp @@ -20,6 +20,9 @@ #include #include #endif +#if defined(__NetBSD__) +#include +#endif // lldb Includes #include "lldb/Core/Error.h" @@ -29,6 +32,9 @@ using namespace lldb; using namespace lldb_private; +const char * +FileSystem::DEV_NULL = "/dev/null"; + FileSpec::PathSyntax FileSystem::GetNativePathSyntax() { @@ -179,6 +185,16 @@ FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst) return error; } +int +FileSystem::GetHardlinkCount(const FileSpec &file_spec) +{ + struct stat file_stat; + if (::stat(file_spec.GetCString(), &file_stat) == 0) + return file_stat.st_nlink; + + return -1; +} + Error FileSystem::Symlink(const FileSpec &src, const FileSpec &dst) { @@ -213,6 +229,34 @@ FileSystem::Readlink(const FileSpec &src, FileSpec &dst) return error; } +Error +FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) +{ + char resolved_path[PATH_MAX]; + if (!src.GetPath (resolved_path, sizeof (resolved_path))) + { + return Error("Couldn't get the canonical path for %s", src.GetCString()); + } + + char real_path[PATH_MAX + 1]; + if (realpath(resolved_path, real_path) == nullptr) + { + Error err; + err.SetErrorToErrno(); + return err; + } + + dst = FileSpec(real_path, false); + + return Error(); +} + +#if defined(__NetBSD__) +static bool IsLocal(const struct statvfs& info) +{ + return (info.f_flag & MNT_LOCAL) != 0; +} +#else static bool IsLocal(const struct statfs& info) { #ifdef __linux__ @@ -230,7 +274,19 @@ static bool IsLocal(const struct statfs& info) return (info.f_flags & MNT_LOCAL) != 0; #endif } +#endif +#if defined(__NetBSD__) +bool +FileSystem::IsLocal(const FileSpec &spec) +{ + struct statvfs statfs_info; + std::string path (spec.GetPath()); + if (statvfs(path.c_str(), &statfs_info) == 0) + return ::IsLocal(statfs_info); + return false; +} +#else bool FileSystem::IsLocal(const FileSpec &spec) { @@ -240,3 +296,4 @@ FileSystem::IsLocal(const FileSpec &spec) return ::IsLocal(statfs_info); return false; } +#endif diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp index c04db71e1b81..cfdbf5635ad1 100644 --- a/source/Host/posix/HostInfoPosix.cpp +++ b/source/Host/posix/HostInfoPosix.cpp @@ -7,7 +7,10 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" +#if !defined(LLDB_DISABLE_PYTHON) +#include "Plugins/ScriptInterpreter/Python/lldb-python.h" +#endif + #include "lldb/Core/Log.h" #include "lldb/Host/posix/HostInfoPosix.h" @@ -19,6 +22,7 @@ #include #include #include +#include #include #include @@ -211,16 +215,29 @@ HostInfoPosix::ComputePythonDirectory(FileSpec &file_spec) char raw_path[PATH_MAX]; lldb_file_spec.GetPath(raw_path, sizeof(raw_path)); +#if defined(LLDB_PYTHON_RELATIVE_LIBDIR) + // Build the path by backing out of the lib dir, then building + // with whatever the real python interpreter uses. (e.g. lib + // for most, lib64 on RHEL x86_64). + char python_path[PATH_MAX]; + ::snprintf(python_path, sizeof(python_path), "%s/../%s", raw_path, LLDB_PYTHON_RELATIVE_LIBDIR); + + char final_path[PATH_MAX]; + realpath(python_path, final_path); + file_spec.GetDirectory().SetCString(final_path); + + return true; +#else llvm::SmallString<256> python_version_dir; llvm::raw_svector_ostream os(python_version_dir); os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages"; - os.flush(); // We may get our string truncated. Should we protect this with an assert? ::strncat(raw_path, python_version_dir.c_str(), sizeof(raw_path) - strlen(raw_path) - 1); file_spec.GetDirectory().SetCString(raw_path); return true; +#endif #else return false; #endif diff --git a/source/Host/posix/MainLoopPosix.cpp b/source/Host/posix/MainLoopPosix.cpp index cb213b9b79f1..897f2d13c0c6 100644 --- a/source/Host/posix/MainLoopPosix.cpp +++ b/source/Host/posix/MainLoopPosix.cpp @@ -94,10 +94,10 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error) } void -MainLoopPosix::UnregisterReadObject(const lldb::IOObjectSP &object_sp) +MainLoopPosix::UnregisterReadObject(IOObject::WaitableHandle handle) { - bool erased = m_read_fds.erase(object_sp->GetWaitableHandle()); - (void) erased; + bool erased = m_read_fds.erase(handle); + UNUSED_IF_ASSERT_DISABLED(erased); assert(erased); } diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp index 0ed319facf93..353faae1628e 100644 --- a/source/Host/posix/PipePosix.cpp +++ b/source/Host/posix/PipePosix.cpp @@ -13,6 +13,12 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) +#ifndef _GLIBCXX_USE_NANOSLEEP +#define _GLIBCXX_USE_NANOSLEEP +#endif +#endif + #include #include @@ -30,9 +36,9 @@ int PipePosix::kInvalidDescriptor = -1; enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE -// pipe2 is supported by Linux, FreeBSD v10 and higher. +// pipe2 is supported by a limited set of platforms // TODO: Add more platforms that support pipe2. -#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) +#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__) #define PIPE2_SUPPORTED 1 #else #define PIPE2_SUPPORTED 0 diff --git a/source/Initialization/SystemInitializerCommon.cpp b/source/Initialization/SystemInitializerCommon.cpp index 51f32a2776a8..6cbc0b707df4 100644 --- a/source/Initialization/SystemInitializerCommon.cpp +++ b/source/Initialization/SystemInitializerCommon.cpp @@ -13,8 +13,8 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Core/Log.h" #include "lldb/Core/Timer.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" - +#include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/ClangASTContext.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" @@ -26,17 +26,19 @@ #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" #include "Plugins/OperatingSystem/Python/OperatingSystemPython.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" #include "Plugins/Platform/Linux/PlatformLinux.h" -#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" #include "Plugins/Platform/MacOSX/PlatformMacOSX.h" #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" +#include "Plugins/Platform/NetBSD/PlatformNetBSD.h" #include "Plugins/Platform/Windows/PlatformWindows.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #if defined(__APPLE__) +#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h" @@ -48,7 +50,7 @@ #if defined(_MSC_VER) #include "lldb/Host/windows/windows.h" -#include "Plugins/Process/Windows/ProcessWindowsLog.h" +#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" #endif #include "llvm/Support/TargetSelect.h" @@ -103,6 +105,9 @@ SystemInitializerCommon::Initialize() process_gdb_remote::ProcessGDBRemoteLog::Initialize(); // Initialize plug-ins + ClangASTContext::Initialize(); + GoASTContext::Initialize(); + ObjectContainerBSDArchive::Initialize(); ObjectFileELF::Initialize(); ObjectFilePECOFF::Initialize(); @@ -110,6 +115,7 @@ SystemInitializerCommon::Initialize() DynamicLoaderWindowsDYLD::Initialize(); platform_freebsd::PlatformFreeBSD::Initialize(); platform_linux::PlatformLinux::Initialize(); + platform_netbsd::PlatformNetBSD::Initialize(); PlatformWindows::Initialize(); PlatformKalimba::Initialize(); platform_android::PlatformAndroid::Initialize(); @@ -126,9 +132,9 @@ SystemInitializerCommon::Initialize() PlatformRemoteiOS::Initialize(); PlatformMacOSX::Initialize(); - PlatformiOSSimulator::Initialize(); #if defined(__APPLE__) + PlatformiOSSimulator::Initialize(); DynamicLoaderDarwinKernel::Initialize(); PlatformDarwinKernel::Initialize(); ObjectFileMachO::Initialize(); @@ -141,9 +147,9 @@ SystemInitializerCommon::Initialize() ProcessWindowsLog::Initialize(); #endif #ifndef LLDB_DISABLE_PYTHON - ScriptInterpreterPython::InitializePrivate(); OperatingSystemPython::Initialize(); #endif + OperatingSystemGo::Initialize(); } void @@ -157,6 +163,7 @@ SystemInitializerCommon::Terminate() DynamicLoaderWindowsDYLD::Terminate(); platform_freebsd::PlatformFreeBSD::Terminate(); platform_linux::PlatformLinux::Terminate(); + platform_netbsd::PlatformNetBSD::Terminate(); PlatformWindows::Terminate(); PlatformKalimba::Terminate(); platform_android::PlatformAndroid::Terminate(); @@ -164,25 +171,29 @@ SystemInitializerCommon::Terminate() ObjectContainerUniversalMachO::Terminate(); PlatformMacOSX::Terminate(); PlatformRemoteiOS::Terminate(); - PlatformiOSSimulator::Terminate(); + + ClangASTContext::Terminate(); + GoASTContext::Terminate(); EmulateInstructionARM::Terminate(); EmulateInstructionMIPS::Terminate(); EmulateInstructionMIPS64::Terminate(); #if defined(__APPLE__) + PlatformiOSSimulator::Terminate(); DynamicLoaderDarwinKernel::Terminate(); ObjectFileMachO::Terminate(); PlatformDarwinKernel::Terminate(); #endif -#if defined(__WIN32__) +#if defined(_MSC_VER) ProcessWindowsLog::Terminate(); #endif #ifndef LLDB_DISABLE_PYTHON OperatingSystemPython::Terminate(); #endif + OperatingSystemGo::Terminate(); Log::Terminate(); } diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp index 2258c26e6c39..81e6b0aa1dbc 100644 --- a/source/Interpreter/Args.cpp +++ b/source/Interpreter/Args.cpp @@ -371,7 +371,7 @@ char ** Args::GetArgumentVector() { if (!m_argv.empty()) - return (char **)&m_argv[0]; + return const_cast(&m_argv[0]); return nullptr; } @@ -379,7 +379,7 @@ const char ** Args::GetConstArgumentVector() const { if (!m_argv.empty()) - return (const char **)&m_argv[0]; + return const_cast(&m_argv[0]); return nullptr; } @@ -575,7 +575,8 @@ Args::ParseOptions (Options &options) } } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); int val; while (1) { @@ -719,7 +720,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add else { // Since the compiler can't handle things like "main + 12" we should - // try to do this for now. The compliler doesn't like adding offsets + // try to do this for now. The compiler doesn't like adding offsets // to function pointer types. static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); RegularExpression::Match regex_match(3); @@ -1189,7 +1190,8 @@ Args::ParseAliasOptions (Options &options, } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); int val; while (1) { @@ -1366,7 +1368,8 @@ Args::ParseArgsForCompletion } } - OptionParser::Prepare(); + Mutex::Locker options_locker(NULL); + OptionParser::Prepare(options_locker); OptionParser::EnableError(false); int val; @@ -1387,7 +1390,7 @@ Args::ParseArgsForCompletion int long_options_index = -1; val = OptionParser::Parse (dummy_vec.size() - 1, - (char *const *) &dummy_vec.front(), + const_cast(&dummy_vec.front()), sstr.GetData(), long_options, &long_options_index); @@ -1668,3 +1671,33 @@ Args::ExpandEscapedCharacters (const char *src, std::string &dst) } } +std::string +Args::EscapeLLDBCommandArgument (const std::string& arg, char quote_char) +{ + const char* chars_to_escape = nullptr; + switch (quote_char) + { + case '\0': + chars_to_escape = " \t\\'\"`"; + break; + case '\'': + chars_to_escape = ""; + break; + case '"': + chars_to_escape = "$\"`\\"; + break; + default: + assert(false && "Unhandled quote character"); + } + + std::string res; + res.reserve(arg.size()); + for (char c : arg) + { + if (::strchr(chars_to_escape, c)) + res.push_back('\\'); + res.push_back(c); + } + return res; +} + diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp index 1da541b8c00f..b7cc607e8070 100644 --- a/source/Interpreter/CommandInterpreter.cpp +++ b/source/Interpreter/CommandInterpreter.cpp @@ -41,9 +41,9 @@ #include "../Commands/CommandObjectWatchpoint.h" #include "../Commands/CommandObjectLanguage.h" - #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" @@ -62,8 +62,6 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" -#include "lldb/Interpreter/ScriptInterpreterNone.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Target/Process.h" @@ -87,6 +85,7 @@ 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, "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, "If true, blank lines will be printed between between REPL submissions." }, { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr } }; @@ -94,7 +93,8 @@ enum { ePropertyExpandRegexAliases = 0, ePropertyPromptOnQuit = 1, - ePropertyStopCmdSourceOnError = 2 + ePropertyStopCmdSourceOnError = 2, + eSpaceReplPrompts = 3 }; ConstString & @@ -104,29 +104,23 @@ CommandInterpreter::GetStaticBroadcasterClass () return class_name; } -CommandInterpreter::CommandInterpreter -( - Debugger &debugger, - ScriptLanguage script_language, - bool synchronous_execution -) : - Broadcaster (&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), - Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), - IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand), - m_debugger (debugger), - m_synchronous_execution (synchronous_execution), - m_skip_lldbinit_files (false), - m_skip_app_init_files (false), - m_script_interpreter_ap (), - m_command_io_handler_sp (), - m_comment_char ('#'), - m_batch_command_mode (false), - m_truncation_warning(eNoTruncation), - m_command_source_depth (0), - m_num_errors(0), - m_quit_requested(false), - m_stopped_for_crash(false) - +CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution) + : Broadcaster(&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), + Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), + IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), + m_debugger(debugger), + m_synchronous_execution(synchronous_execution), + m_skip_lldbinit_files(false), + m_skip_app_init_files(false), + m_script_interpreter_sp(), + m_command_io_handler_sp(), + m_comment_char('#'), + m_batch_command_mode(false), + m_truncation_warning(eNoTruncation), + m_command_source_depth(0), + m_num_errors(0), + m_quit_requested(false), + m_stopped_for_crash(false) { debugger.SetScriptLanguage (script_language); SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); @@ -175,6 +169,13 @@ CommandInterpreter::GetStopCmdSourceOnError () const return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); } +bool +CommandInterpreter::GetSpaceReplPrompts () const +{ + const uint32_t idx = eSpaceReplPrompts; + return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); +} + void CommandInterpreter::Initialize () { @@ -360,11 +361,19 @@ CommandInterpreter::Initialize () #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); #else + #if defined(__APPLE__) + std::string shell_option; + shell_option.append("--shell-expand-args"); + shell_option.append(" true"); + shell_option.append(" --"); + ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); + #else std::string shell_option; shell_option.append("--shell="); shell_option.append(HostInfo::GetDefaultShell().GetPath()); shell_option.append(" --"); ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); + #endif #endif AddAlias ("r", cmd_obj_sp); AddAlias ("run", cmd_obj_sp); @@ -392,9 +401,9 @@ void CommandInterpreter::Clear() { m_command_io_handler_sp.reset(); - - if (m_script_interpreter_ap) - m_script_interpreter_ap->Clear(); + + if (m_script_interpreter_sp) + m_script_interpreter_sp->Clear(); } const char * @@ -511,8 +520,7 @@ CommandInterpreter::LoadCommandDictionary () char buffer[1024]; int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); assert (num_printed < 1024); - // Quiet unused variable warning for release builds. - (void) num_printed; + UNUSED_IF_ASSERT_DISABLED(num_printed); success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); if (!success) break; @@ -2011,7 +2019,7 @@ CommandInterpreter::HandleCompletion (const char *current_line, matches); if (num_command_matches <= 0) - return num_command_matches; + return num_command_matches; if (num_args == 0) { @@ -2030,18 +2038,18 @@ CommandInterpreter::HandleCompletion (const char *current_line, std::string common_prefix; matches.LongestCommonPrefix (common_prefix); const size_t partial_name_len = command_partial_str.size(); + common_prefix.erase (0, partial_name_len); // If we matched a unique single command, add a space... // Only do this if the completer told us this was a complete word, however... if (num_command_matches == 1 && word_complete) { char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); + common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); if (quote_char != '\0') common_prefix.push_back(quote_char); - common_prefix.push_back(' '); } - common_prefix.erase (0, partial_name_len); matches.InsertStringAtIndex(0, common_prefix.c_str()); } return num_command_matches; @@ -2709,48 +2717,19 @@ CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, } ScriptInterpreter * -CommandInterpreter::GetScriptInterpreter (bool can_create) +CommandInterpreter::GetScriptInterpreter(bool can_create) { - if (m_script_interpreter_ap.get() != nullptr) - return m_script_interpreter_ap.get(); - + if (m_script_interpreter_sp) + return m_script_interpreter_sp.get(); + if (!can_create) return nullptr; - - // - // we need to protect the initialization of the script interpreter - // otherwise we could end up with two threads both trying to create - // their instance of it, and for some languages (e.g. Python) - // this is a bulletproof recipe for disaster! - // this needs to be a function-level static because multiple Debugger instances living in the same process - // still need to be isolated and not try to initialize Python concurrently - static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive); - Mutex::Locker interpreter_lock(g_interpreter_mutex); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("Initializing the ScriptInterpreter now\n"); - + lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); - switch (script_lang) - { - case eScriptLanguagePython: -#ifndef LLDB_DISABLE_PYTHON - m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this)); - break; -#else - // Fall through to the None case when python is disabled -#endif - case eScriptLanguageNone: - m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this)); - break; - }; - - return m_script_interpreter_ap.get(); + m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); + return m_script_interpreter_sp.get(); } - - bool CommandInterpreter::GetSynchronous () { diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp index c0efd9e33c08..616d3e38acbb 100644 --- a/source/Interpreter/CommandObject.cpp +++ b/source/Interpreter/CommandObject.cpp @@ -28,6 +28,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Language.h" + #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -395,7 +397,7 @@ CommandObject::HandleCompletion StringList &matches ) { - // Default implmentation of WantsCompletion() is !WantsRawCommandString(). + // Default implementation of WantsCompletion() is !WantsRawCommandString(). // Subclasses who want raw command string but desire, for example, // argument completion should override WantsCompletion() to return true, // instead. @@ -848,7 +850,7 @@ LanguageTypeHelpTextCallback () StreamString sstr; sstr << "One of the following languages:\n"; - LanguageRuntime::PrintAllLanguages(sstr, " ", "\n"); + Language::PrintAllLanguages(sstr, " ", "\n"); sstr.Flush(); diff --git a/source/Interpreter/CommandObjectScript.h b/source/Interpreter/CommandObjectScript.h index fd55fc44a46a..5365aaac4cbe 100644 --- a/source/Interpreter/CommandObjectScript.h +++ b/source/Interpreter/CommandObjectScript.h @@ -25,18 +25,16 @@ namespace lldb_private { class CommandObjectScript : public CommandObjectRaw { public: + CommandObjectScript(CommandInterpreter &interpreter, + lldb::ScriptLanguage script_lang); - CommandObjectScript (CommandInterpreter &interpreter, - lldb::ScriptLanguage script_lang); - - virtual - ~CommandObjectScript (); + ~CommandObjectScript() override; protected: - virtual bool - DoExecute (const char *command, CommandReturnObject &result); + bool + DoExecute(const char *command, CommandReturnObject &result) override; }; } // namespace lldb_private -#endif // liblldb_CommandObjectScript_h_ +#endif // liblldb_CommandObjectScript_h_ diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp index e5a5c004b2da..bbd966859c34 100644 --- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp +++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp @@ -162,7 +162,7 @@ OptionGroupValueObjectDisplay::GetAsDumpOptions (LanguageRuntimeDescriptionDispl lldb::TypeSummaryImplSP summary_sp) { DumpValueObjectOptions options; - options.SetMaximumPointerDepth(ptr_depth); + options.SetMaximumPointerDepth( {DumpValueObjectOptions::PointerDepth::Mode::Always,ptr_depth} ); if (use_objc) options.SetShowSummary(false); else diff --git a/source/Interpreter/OptionValueLanguage.cpp b/source/Interpreter/OptionValueLanguage.cpp index fd46553dabde..dd7173c3dc74 100644 --- a/source/Interpreter/OptionValueLanguage.cpp +++ b/source/Interpreter/OptionValueLanguage.cpp @@ -16,7 +16,7 @@ #include "lldb/Core/Stream.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; @@ -30,7 +30,7 @@ OptionValueLanguage::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, u { if (dump_mask & eDumpOptionType) strm.PutCString (" = "); - strm.PutCString (LanguageRuntime::GetNameForLanguageType(m_current_value)); + strm.PutCString (Language::GetNameForLanguageType(m_current_value)); } } @@ -47,9 +47,28 @@ OptionValueLanguage::SetValueFromString (llvm::StringRef value, VarSetOperationT case eVarSetOperationReplace: case eVarSetOperationAssign: { - LanguageType new_type = LanguageRuntime::GetLanguageTypeFromString(value.data()); - m_value_was_set = true; - m_current_value = new_type; + ConstString lang_name(value.trim()); + std::set languages_for_types; + std::set languages_for_expressions; + Language::GetLanguagesSupportingTypeSystems(languages_for_types, languages_for_expressions); + + LanguageType new_type = Language::GetLanguageTypeFromString(lang_name.GetCString()); + if (new_type && languages_for_types.count(new_type)) + { + m_value_was_set = true; + m_current_value = new_type; + } + else + { + StreamString error_strm; + error_strm.Printf("invalid language type '%s', ", value.str().c_str()); + error_strm.Printf("valid values are:\n"); + for (lldb::LanguageType language : languages_for_types) + { + error_strm.Printf("%s%s%s", " ", Language::GetNameForLanguageType(language), "\n"); + } + error.SetErrorString(error_strm.GetData()); + } } break; diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp index e8d870a99cf8..a3c28f70270f 100644 --- a/source/Interpreter/OptionValueProperties.cpp +++ b/source/Interpreter/OptionValueProperties.cpp @@ -311,6 +311,15 @@ OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionConte return nullptr; } +OptionValueLanguage * +OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage (const ExecutionContext *exe_ctx, uint32_t idx) const +{ + const Property *property = GetPropertyAtIndex (exe_ctx, false, idx); + if (property) + return property->GetValue()->GetAsLanguage(); + return nullptr; +} + bool OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const { diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp index 077fcbc54cc3..b9fe28620a4f 100644 --- a/source/Interpreter/Property.cpp +++ b/source/Interpreter/Property.cpp @@ -17,7 +17,7 @@ #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValues.h" -#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Language.h" using namespace lldb; using namespace lldb_private; @@ -129,7 +129,7 @@ Property::Property (const PropertyDefinition &definition) : { LanguageType new_lang = eLanguageTypeUnknown; if (definition.default_cstr_value) - LanguageRuntime::GetLanguageTypeFromString(definition.default_cstr_value); + Language::GetLanguageTypeFromString(definition.default_cstr_value); else new_lang = (LanguageType)definition.default_uint_value; m_value_sp.reset (new OptionValueLanguage(new_lang)); diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp deleted file mode 100644 index a581a0b3601a..000000000000 --- a/source/Interpreter/PythonDataObjects.cpp +++ /dev/null @@ -1,524 +0,0 @@ -//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// In order to guarantee correct working with Python, Python.h *MUST* be -// the *FIRST* header file included here. -#ifdef LLDB_DISABLE_PYTHON - -// Python is disabled in this build - -#else - -#include "lldb/lldb-python.h" - -#include - -#include "lldb/Core/Stream.h" -#include "lldb/Host/File.h" -#include "lldb/Interpreter/PythonDataObjects.h" -#include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" - -using namespace lldb_private; -using namespace lldb; - -void -StructuredPythonObject::Dump(Stream &s) const -{ - s << "Python Obj: 0x" << GetValue(); -} - -//---------------------------------------------------------------------- -// PythonObject -//---------------------------------------------------------------------- - -void -PythonObject::Dump (Stream &strm) const -{ - if (m_py_obj) - { - FILE *file = ::tmpfile(); - if (file) - { - ::PyObject_Print (m_py_obj, file, 0); - const long length = ftell (file); - if (length) - { - ::rewind(file); - std::vector file_contents (length,'\0'); - const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); - if (length_read > 0) - strm.Write (file_contents.data(), length_read); - } - ::fclose (file); - } - } - else - strm.PutCString ("NULL"); -} - -PyObjectType -PythonObject::GetObjectType() const -{ - if (IsNULLOrNone()) - return PyObjectType::None; - - if (PyList_Check(m_py_obj)) - return PyObjectType::List; - if (PyDict_Check(m_py_obj)) - return PyObjectType::Dictionary; - if (PyString_Check(m_py_obj)) - return PyObjectType::String; - if (PyInt_Check(m_py_obj) || PyLong_Check(m_py_obj)) - return PyObjectType::Integer; - return PyObjectType::Unknown; -} - -PythonString -PythonObject::Repr () -{ - if (!m_py_obj) - return PythonString (); - PyObject *repr = PyObject_Repr(m_py_obj); - if (!repr) - return PythonString (); - return PythonString(repr); -} - -PythonString -PythonObject::Str () -{ - if (!m_py_obj) - return PythonString (); - PyObject *str = PyObject_Str(m_py_obj); - if (!str) - return PythonString (); - return PythonString(str); -} - -bool -PythonObject::IsNULLOrNone () const -{ - return ((m_py_obj == nullptr) || (m_py_obj == Py_None)); -} - -StructuredData::ObjectSP -PythonObject::CreateStructuredObject() const -{ - switch (GetObjectType()) - { - case PyObjectType::Dictionary: - return PythonDictionary(m_py_obj).CreateStructuredDictionary(); - case PyObjectType::Integer: - return PythonInteger(m_py_obj).CreateStructuredInteger(); - case PyObjectType::List: - return PythonList(m_py_obj).CreateStructuredArray(); - case PyObjectType::String: - return PythonString(m_py_obj).CreateStructuredString(); - case PyObjectType::None: - return StructuredData::ObjectSP(); - default: - return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); - } -} - -//---------------------------------------------------------------------- -// PythonString -//---------------------------------------------------------------------- - -PythonString::PythonString (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a string -} - -PythonString::PythonString (llvm::StringRef string) : - PythonObject(PyString_FromStringAndSize(string.data(), string.size())) -{ -} - -PythonString::PythonString(const char *string) : - PythonObject(PyString_FromString(string)) -{ -} - -PythonString::PythonString () : - PythonObject() -{ -} - -PythonString::~PythonString () -{ -} - -bool -PythonString::Reset (PyObject *py_obj) -{ - if (py_obj && PyString_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -llvm::StringRef -PythonString::GetString() const -{ - if (m_py_obj) - return llvm::StringRef(PyString_AsString(m_py_obj), GetSize()); - return llvm::StringRef(); -} - -size_t -PythonString::GetSize() const -{ - if (m_py_obj) - return PyString_Size(m_py_obj); - return 0; -} - -void -PythonString::SetString (llvm::StringRef string) -{ - PythonObject::Reset(PyString_FromStringAndSize(string.data(), string.size())); -} - -StructuredData::StringSP -PythonString::CreateStructuredString() const -{ - StructuredData::StringSP result(new StructuredData::String); - result->SetValue(GetString()); - return result; -} - -//---------------------------------------------------------------------- -// PythonInteger -//---------------------------------------------------------------------- - -PythonInteger::PythonInteger (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a integer type -} - -PythonInteger::PythonInteger (int64_t value) : - PythonObject() -{ - SetInteger (value); -} - - -PythonInteger::~PythonInteger () -{ -} - -bool -PythonInteger::Reset (PyObject *py_obj) -{ - if (py_obj) - { - if (PyInt_Check (py_obj) || PyLong_Check(py_obj)) - return PythonObject::Reset(py_obj); - } - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -int64_t -PythonInteger::GetInteger() const -{ - if (m_py_obj) - { - if (PyInt_Check(m_py_obj)) - return PyInt_AsLong(m_py_obj); - else if (PyLong_Check(m_py_obj)) - return PyLong_AsLongLong(m_py_obj); - } - return UINT64_MAX; -} - -void -PythonInteger::SetInteger (int64_t value) -{ - PythonObject::Reset(PyLong_FromLongLong(value)); -} - -StructuredData::IntegerSP -PythonInteger::CreateStructuredInteger() const -{ - StructuredData::IntegerSP result(new StructuredData::Integer); - result->SetValue(GetInteger()); - return result; -} - -//---------------------------------------------------------------------- -// PythonList -//---------------------------------------------------------------------- - -PythonList::PythonList (bool create_empty) : - PythonObject(create_empty ? PyList_New(0) : nullptr) -{ -} - -PythonList::PythonList (uint32_t count) : - PythonObject(PyList_New(count)) -{ -} - -PythonList::PythonList (PyObject *py_obj) : - PythonObject() -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a list -} - - -PythonList::PythonList (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a list -} - -PythonList::~PythonList () -{ -} - -bool -PythonList::Reset (PyObject *py_obj) -{ - if (py_obj && PyList_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -uint32_t -PythonList::GetSize() const -{ - if (m_py_obj) - return PyList_GET_SIZE(m_py_obj); - return 0; -} - -PythonObject -PythonList::GetItemAtIndex(uint32_t index) const -{ - if (m_py_obj) - return PythonObject(PyList_GetItem(m_py_obj, index)); - return PythonObject(); -} - -void -PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object) -{ - if (m_py_obj && object) - PyList_SetItem(m_py_obj, index, object.get()); -} - -void -PythonList::AppendItem (const PythonObject &object) -{ - if (m_py_obj && object) - PyList_Append(m_py_obj, object.get()); -} - -StructuredData::ArraySP -PythonList::CreateStructuredArray() const -{ - StructuredData::ArraySP result(new StructuredData::Array); - uint32_t count = GetSize(); - for (uint32_t i = 0; i < count; ++i) - { - PythonObject obj = GetItemAtIndex(i); - result->AddItem(obj.CreateStructuredObject()); - } - return result; -} - -//---------------------------------------------------------------------- -// PythonDictionary -//---------------------------------------------------------------------- - -PythonDictionary::PythonDictionary (bool create_empty) : -PythonObject(create_empty ? PyDict_New() : nullptr) -{ -} - -PythonDictionary::PythonDictionary (PyObject *py_obj) : - PythonObject(py_obj) -{ - Reset(py_obj); // Use "Reset()" to ensure that py_obj is a dictionary -} - - -PythonDictionary::PythonDictionary (const PythonObject &object) : - PythonObject() -{ - Reset(object.get()); // Use "Reset()" to ensure that py_obj is a dictionary -} - -PythonDictionary::~PythonDictionary () -{ -} - -bool -PythonDictionary::Reset (PyObject *py_obj) -{ - if (py_obj && PyDict_Check(py_obj)) - return PythonObject::Reset(py_obj); - - PythonObject::Reset(nullptr); - return py_obj == nullptr; -} - -uint32_t -PythonDictionary::GetSize() const -{ - if (m_py_obj) - return PyDict_Size(m_py_obj); - return 0; -} - -PythonObject -PythonDictionary::GetItemForKey (const char *key) const -{ - if (key && key[0]) - { - PythonString python_key(key); - return GetItemForKey(python_key); - } - return PythonObject(); -} - - -PythonObject -PythonDictionary::GetItemForKey (const PythonString &key) const -{ - if (m_py_obj && key) - return PythonObject(PyDict_GetItem(m_py_obj, key.get())); - return PythonObject(); -} - - -const char * -PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const -{ - if (m_py_obj && key) - { - PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get()); - if (py_obj && PyString_Check(py_obj)) - return PyString_AsString(py_obj); - } - return fail_value; -} - -int64_t -PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const -{ - if (m_py_obj && key) - { - PyObject *py_obj = PyDict_GetItem(m_py_obj, key.get()); - if (py_obj) - { - if (PyInt_Check(py_obj)) - return PyInt_AsLong(py_obj); - - if (PyLong_Check(py_obj)) - return PyLong_AsLong(py_obj); - } - } - return fail_value; -} - -PythonList -PythonDictionary::GetKeys () const -{ - if (m_py_obj) - return PythonList(PyDict_Keys(m_py_obj)); - return PythonList(true); -} - -PythonString -PythonDictionary::GetKeyAtPosition (uint32_t pos) const -{ - PyObject *key, *value; - Py_ssize_t pos_iter = 0; - - if (m_py_obj) - { - while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) - { - if (pos-- == 0) - return PythonString(key); - } - } - return PythonString(); -} - -PythonObject -PythonDictionary::GetValueAtPosition (uint32_t pos) const -{ - PyObject *key, *value; - Py_ssize_t pos_iter = 0; - - if (!m_py_obj) - return PythonObject(); - - while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) { - if (pos-- == 0) - return PythonObject(value); - } - return PythonObject(); -} - -void -PythonDictionary::SetItemForKey (const PythonString &key, PyObject *value) -{ - if (m_py_obj && key && value) - PyDict_SetItem(m_py_obj, key.get(), value); -} - -void -PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value) -{ - if (m_py_obj && key && value) - PyDict_SetItem(m_py_obj, key.get(), value.get()); -} - -StructuredData::DictionarySP -PythonDictionary::CreateStructuredDictionary() const -{ - StructuredData::DictionarySP result(new StructuredData::Dictionary); - PythonList keys(GetKeys()); - uint32_t num_keys = keys.GetSize(); - for (uint32_t i = 0; i < num_keys; ++i) - { - PythonObject key = keys.GetItemAtIndex(i); - PythonString key_str = key.Str(); - PythonObject value = GetItemForKey(key); - StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); - result->AddItem(key_str.GetString(), structured_value); - } - return result; -} - -#endif diff --git a/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp deleted file mode 100644 index 909a1161c9c1..000000000000 --- a/source/Interpreter/ScriptInterpreterNone.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Interpreter/ScriptInterpreterNone.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/StringList.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Interpreter/CommandInterpreter.h" - -using namespace lldb; -using namespace lldb_private; - -ScriptInterpreterNone::ScriptInterpreterNone (CommandInterpreter &interpreter) : - ScriptInterpreter (interpreter, eScriptLanguageNone) -{ -} - -ScriptInterpreterNone::~ScriptInterpreterNone () -{ -} - -bool -ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, const ExecuteScriptOptions&) -{ - m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n"); - return false; -} - -void -ScriptInterpreterNone::ExecuteInterpreterLoop () -{ - m_interpreter.GetDebugger().GetErrorFile()->PutCString ("error: there is no embedded script interpreter in this mode.\n"); -} - - diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp deleted file mode 100644 index 8f60793550c3..000000000000 --- a/source/Interpreter/ScriptInterpreterPython.cpp +++ /dev/null @@ -1,3194 +0,0 @@ -//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// In order to guarantee correct working with Python, Python.h *MUST* be -// the *FIRST* header file included here. -#ifdef LLDB_DISABLE_PYTHON - -// Python is disabled in this build - -#else - -#include "lldb/lldb-python.h" -#include "lldb/Interpreter/ScriptInterpreterPython.h" - -#include -#include - -#include - -#include "lldb/API/SBValue.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Breakpoint/WatchpointOptions.h" -#include "lldb/Core/Communication.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Timer.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/DataFormatters/TypeSummary.h" -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/Pipe.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/PythonDataObjects.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlan.h" - -#if defined(_WIN32) -#include "lldb/Host/windows/ConnectionGenericFileWindows.h" -#endif - -#include "llvm/ADT/StringRef.h" - -using namespace lldb; -using namespace lldb_private; - -static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr; -static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; -static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; -static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr; -static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; -static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; -static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; -static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; -static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; -static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; -static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr; -static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr; -static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; -static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; -static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; -static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; -static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; - -static bool g_initialized = false; - -static std::string -ReadPythonBacktrace (PyObject* py_backtrace); - -ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter, - uint16_t on_entry, - uint16_t on_leave, - FILE *in, - FILE *out, - FILE *err) : - ScriptInterpreterLocker (), - m_teardown_session( (on_leave & TearDownSession) == TearDownSession ), - m_python_interpreter(py_interpreter) -{ - DoAcquireLock(); - if ((on_entry & InitSession) == InitSession) - { - if (DoInitSession(on_entry, in, out, err) == false) - { - // Don't teardown the session if we didn't init it. - m_teardown_session = false; - } - } -} - -bool -ScriptInterpreterPython::Locker::DoAcquireLock() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - m_GILState = PyGILState_Ensure(); - if (log) - log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); - - // we need to save the thread state when we first start the command - // because we might decide to interrupt it while some action is taking - // place outside of Python (e.g. printing to screen, waiting for the network, ...) - // in that case, _PyThreadState_Current will be NULL - and we would be unable - // to set the asynchronous exception - not a desirable situation - m_python_interpreter->SetThreadState (_PyThreadState_Current); - m_python_interpreter->IncrementLockCount(); - return true; -} - -bool -ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err) -{ - if (!m_python_interpreter) - return false; - return m_python_interpreter->EnterSession (on_entry_flags, in, out, err); -} - -bool -ScriptInterpreterPython::Locker::DoFreeLock() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - if (log) - log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); - PyGILState_Release(m_GILState); - m_python_interpreter->DecrementLockCount(); - return true; -} - -bool -ScriptInterpreterPython::Locker::DoTearDownSession() -{ - if (!m_python_interpreter) - return false; - m_python_interpreter->LeaveSession (); - return true; -} - -ScriptInterpreterPython::Locker::~Locker() -{ - if (m_teardown_session) - DoTearDownSession(); - DoFreeLock(); -} - - -ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) : - ScriptInterpreter (interpreter, eScriptLanguagePython), - IOHandlerDelegateMultiline("DONE"), - m_saved_stdin (), - m_saved_stdout (), - m_saved_stderr (), - m_main_module (), - m_lldb_module (), - m_session_dict (false), // Don't create an empty dictionary, leave it invalid - m_sys_module_dict (false), // Don't create an empty dictionary, leave it invalid - m_run_one_line_function (), - m_run_one_line_str_global (), - m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()), - m_terminal_state (), - m_active_io_handler (eIOHandlerNone), - m_session_is_active (false), - m_pty_slave_is_open (false), - m_valid_session (true), - m_lock_count (0), - m_command_thread_state (nullptr) -{ - assert(g_initialized && "ScriptInterpreterPython created but initialize has not been called!"); - - m_dictionary_name.append("_dict"); - StreamString run_string; - run_string.Printf ("%s = dict()", m_dictionary_name.c_str()); - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); - PyRun_SimpleString (run_string.GetData()); - - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - - // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set - // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task - run_string.Clear(); - run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(), - interpreter.GetDebugger().GetID()); - PyRun_SimpleString (run_string.GetData()); -} - -ScriptInterpreterPython::~ScriptInterpreterPython () -{ -} - -void -ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler) -{ - const char *instructions = nullptr; - - switch (m_active_io_handler) - { - case eIOHandlerNone: - break; - case eIOHandlerBreakpoint: - instructions = R"(Enter your Python command(s). Type 'DONE' to end. -def function (frame, bp_loc, internal_dict): - """frame: the lldb.SBFrame for the location at which you stopped - bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information - internal_dict: an LLDB support object not to be used""" -)"; - break; - case eIOHandlerWatchpoint: - instructions = "Enter your Python command(s). Type 'DONE' to end.\n"; - break; - } - - if (instructions) - { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - if (output_sp) - { - output_sp->PutCString(instructions); - output_sp->Flush(); - } - } -} - -void -ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data) -{ - io_handler.SetIsDone(true); - bool batch_mode = m_interpreter.GetBatchCommandMode(); - - switch (m_active_io_handler) - { - case eIOHandlerNone: - break; - case eIOHandlerBreakpoint: - { - std::vector *bp_options_vec = (std::vector *)io_handler.GetUserData(); - for (auto bp_options : *bp_options_vec) - { - if (!bp_options) - continue; - - std::unique_ptr data_ap(new BreakpointOptions::CommandData()); - if (data_ap.get()) - { - data_ap->user_source.SplitIntoLines(data); - - if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success()) - { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); - } - else if (!batch_mode) - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - if (error_sp) - { - error_sp->Printf ("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); - } - } - } - } - m_active_io_handler = eIOHandlerNone; - } - break; - case eIOHandlerWatchpoint: - { - WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); - std::unique_ptr data_ap(new WatchpointOptions::CommandData()); - if (data_ap.get()) - { - data_ap->user_source.SplitIntoLines(data); - - if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) - { - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); - } - else if (!batch_mode) - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - if (error_sp) - { - error_sp->Printf ("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); - } - } - } - m_active_io_handler = eIOHandlerNone; - } - break; - } -} - - -void -ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) -{ -} - -void -ScriptInterpreterPython::SaveTerminalState (int fd) -{ - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state - // on the input file handle. - m_terminal_state.Save (fd, false); -} - -void -ScriptInterpreterPython::RestoreTerminalState () -{ - // Python mucks with the terminal state of STDIN. If we can possibly avoid - // this by setting the file handles up correctly prior to entering the - // interpreter we should. For now we save and restore the terminal state - // on the input file handle. - m_terminal_state.Restore(); -} - -void -ScriptInterpreterPython::LeaveSession () -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - if (log) - log->PutCString("ScriptInterpreterPython::LeaveSession()"); - - // checking that we have a valid thread state - since we use our own threading and locking - // in some (rare) cases during cleanup Python may end up believing we have no thread state - // and PyImport_AddModule will crash if that is the case - since that seems to only happen - // when destroying the SBDebugger, we can make do without clearing up stdout and stderr - - // rdar://problem/11292882 - // When the current thread state is NULL, PyThreadState_Get() issues a fatal error. - if (PyThreadState_GetDict()) - { - PythonDictionary &sys_module_dict = GetSysModuleDictionary (); - if (sys_module_dict) - { - if (m_saved_stdin) - { - sys_module_dict.SetItemForKey("stdin", m_saved_stdin); - m_saved_stdin.Reset (); - } - if (m_saved_stdout) - { - sys_module_dict.SetItemForKey("stdout", m_saved_stdout); - m_saved_stdout.Reset (); - } - if (m_saved_stderr) - { - sys_module_dict.SetItemForKey("stderr", m_saved_stderr); - m_saved_stderr.Reset (); - } - } - } - - m_session_is_active = false; -} - -static PyObject * -PyFile_FromFile_Const(FILE *fp, const char *name, const char *mode, int (*close)(FILE *)) -{ - // Read through the Python source, doesn't seem to modify these strings - return PyFile_FromFile(fp, const_cast(name), const_cast(mode), close); -} - -bool -ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, - FILE *in, - FILE *out, - FILE *err) -{ - // If we have already entered the session, without having officially 'left' it, then there is no need to - // 'enter' it again. - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - if (m_session_is_active) - { - if (log) - log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags); - return false; - } - - if (log) - log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags); - - - m_session_is_active = true; - - StreamString run_string; - - if (on_entry_flags & Locker::InitGlobals) - { - run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); - run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); - run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()"); - run_string.PutCString ("; lldb.process = lldb.target.GetProcess()"); - run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()"); - run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()"); - run_string.PutCString ("')"); - } - else - { - // If we aren't initing the globals, we should still always set the debugger (since that is always unique.) - run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); - run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); - run_string.PutCString ("')"); - } - - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - - PythonDictionary &sys_module_dict = GetSysModuleDictionary (); - if (sys_module_dict) - { - lldb::StreamFileSP in_sp; - lldb::StreamFileSP out_sp; - lldb::StreamFileSP err_sp; - if (in == nullptr || out == nullptr || err == nullptr) - m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); - - m_saved_stdin.Reset(); - - if ((on_entry_flags & Locker::NoSTDIN) == 0) - { - // STDIN is enabled - if (in == nullptr && in_sp) - in = in_sp->GetFile().GetStream(); - if (in) - { - m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); - // This call can deadlock your process if the file is locked - PyObject *new_file = PyFile_FromFile_Const (in, "", "r", nullptr); - sys_module_dict.SetItemForKey ("stdin", new_file); - Py_DECREF (new_file); - } - } - - if (out == nullptr && out_sp) - out = out_sp->GetFile().GetStream(); - if (out) - { - m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout")); - - PyObject *new_file = PyFile_FromFile_Const (out, "", "w", nullptr); - sys_module_dict.SetItemForKey ("stdout", new_file); - Py_DECREF (new_file); - } - else - m_saved_stdout.Reset(); - - if (err == nullptr && err_sp) - err = err_sp->GetFile().GetStream(); - if (err) - { - m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr")); - - PyObject *new_file = PyFile_FromFile_Const (err, "", "w", nullptr); - sys_module_dict.SetItemForKey ("stderr", new_file); - Py_DECREF (new_file); - } - else - m_saved_stderr.Reset(); - } - - if (PyErr_Occurred()) - PyErr_Clear (); - - return true; -} - -PythonObject & -ScriptInterpreterPython::GetMainModule () -{ - if (!m_main_module) - m_main_module.Reset(PyImport_AddModule ("__main__")); - return m_main_module; -} - -PythonDictionary & -ScriptInterpreterPython::GetSessionDictionary () -{ - if (!m_session_dict) - { - PythonObject &main_module = GetMainModule (); - if (main_module) - { - PythonDictionary main_dict(PyModule_GetDict (main_module.get())); - if (main_dict) - { - m_session_dict = main_dict.GetItemForKey(m_dictionary_name.c_str()); - } - } - } - return m_session_dict; -} - -PythonDictionary & -ScriptInterpreterPython::GetSysModuleDictionary () -{ - if (!m_sys_module_dict) - { - PyObject *sys_module = PyImport_AddModule ("sys"); - if (sys_module) - m_sys_module_dict.Reset(PyModule_GetDict (sys_module)); - } - return m_sys_module_dict; -} - -static std::string -GenerateUniqueName (const char* base_name_wanted, - uint32_t& functions_counter, - const void* name_token = nullptr) -{ - StreamString sstr; - - if (!base_name_wanted) - return std::string(); - - if (!name_token) - sstr.Printf ("%s_%d", base_name_wanted, functions_counter++); - else - sstr.Printf ("%s_%p", base_name_wanted, name_token); - - return sstr.GetString(); -} - -bool -ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects () -{ - if (!m_run_one_line_function) - { - PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter"); - if (module != nullptr) - { - PythonDictionary module_dict (PyModule_GetDict (module)); - if (module_dict) - { - m_run_one_line_function = module_dict.GetItemForKey("run_one_line"); - m_run_one_line_str_global = module_dict.GetItemForKey("g_run_one_line_str"); - } - } - } - return (bool)m_run_one_line_function; -} - -static void -ReadThreadBytesReceived(void *baton, const void *src, size_t src_len) -{ - if (src && src_len) - { - Stream *strm = (Stream *)baton; - strm->Write(src, src_len); - strm->Flush(); - } -} - -bool -ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options) -{ - if (!m_valid_session) - return false; - - if (command && command[0]) - { - // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through - // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside - // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated - // method to pass the command string directly down to Python. - Debugger &debugger = m_interpreter.GetDebugger(); - - StreamFileSP input_file_sp; - StreamFileSP output_file_sp; - StreamFileSP error_file_sp; - Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); - bool join_read_thread = false; - if (options.GetEnableIO()) - { - if (result) - { - input_file_sp = debugger.GetInputFile(); - // Set output to a temporary file so we can forward the results on to the result object - - Pipe pipe; - Error pipe_result = pipe.CreateNew(false); - if (pipe_result.Success()) - { -#if defined(_WIN32) - lldb::file_t read_file = pipe.GetReadNativeHandle(); - pipe.ReleaseReadFileDescriptor(); - std::unique_ptr conn_ap(new ConnectionGenericFile(read_file, true)); -#else - std::unique_ptr conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); -#endif - if (conn_ap->IsConnected()) - { - output_comm.SetConnection(conn_ap.release()); - output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream()); - output_comm.StartReadThread(); - join_read_thread = true; - FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w"); - output_file_sp.reset(new StreamFile(outfile_handle, true)); - error_file_sp = output_file_sp; - if (outfile_handle) - ::setbuf (outfile_handle, nullptr); - - result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream()); - result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream()); - } - } - } - if (!input_file_sp || !output_file_sp || !error_file_sp) - debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); - } - else - { - input_file_sp.reset (new StreamFile ()); - input_file_sp->GetFile().Open("/dev/null", File::eOpenOptionRead); - output_file_sp.reset (new StreamFile ()); - output_file_sp->GetFile().Open("/dev/null", File::eOpenOptionWrite); - error_file_sp = output_file_sp; - } - - FILE *in_file = input_file_sp->GetFile().GetStream(); - FILE *out_file = output_file_sp->GetFile().GetStream(); - FILE *err_file = error_file_sp->GetFile().GetStream(); - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | - ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN), - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession, - in_file, - out_file, - err_file); - - bool success = false; - - // Find the correct script interpreter dictionary in the main module. - PythonDictionary &session_dict = GetSessionDictionary (); - if (session_dict) - { - if (GetEmbeddedInterpreterModuleObjects ()) - { - PyObject *pfunc = m_run_one_line_function.get(); - - if (pfunc && PyCallable_Check (pfunc)) - { - PythonObject pargs (Py_BuildValue("(Os)", session_dict.get(), command)); - if (pargs) - { - PythonObject return_value(PyObject_CallObject (pfunc, pargs.get())); - if (return_value) - success = true; - else if (options.GetMaskoutErrors() && PyErr_Occurred ()) - { - PyErr_Print(); - PyErr_Clear(); - } - } - } - } - } - - // Flush our output and error file handles - ::fflush (out_file); - if (out_file != err_file) - ::fflush (err_file); - - if (join_read_thread) - { - // Close the write end of the pipe since we are done with our - // one line script. This should cause the read thread that - // output_comm is using to exit - output_file_sp->GetFile().Close(); - // The close above should cause this thread to exit when it gets - // to the end of file, so let it get all its data - output_comm.JoinReadThread(); - // Now we can close the read end of the pipe - output_comm.Disconnect(); - } - - - if (success) - return true; - - // The one-liner failed. Append the error message. - if (result) - result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command); - return false; - } - - if (result) - result->AppendError ("empty command passed to python\n"); - return false; -} - - -class IOHandlerPythonInterpreter : - public IOHandler -{ -public: - - IOHandlerPythonInterpreter (Debugger &debugger, - ScriptInterpreterPython *python) : - IOHandler (debugger, IOHandler::Type::PythonInterpreter), - m_python(python) - { - - } - - ~IOHandlerPythonInterpreter() override - { - - } - - ConstString - GetControlSequence (char ch) override - { - if (ch == 'd') - return ConstString("quit()\n"); - return ConstString(); - } - - void - Run () override - { - if (m_python) - { - int stdin_fd = GetInputFD(); - if (stdin_fd >= 0) - { - Terminal terminal(stdin_fd); - TerminalState terminal_state; - const bool is_a_tty = terminal.IsATerminal(); - - if (is_a_tty) - { - terminal_state.Save (stdin_fd, false); - terminal.SetCanonical(false); - terminal.SetEcho(true); - } - - ScriptInterpreterPython::Locker locker (m_python, - ScriptInterpreterPython::Locker::AcquireLock | - ScriptInterpreterPython::Locker::InitSession | - ScriptInterpreterPython::Locker::InitGlobals, - ScriptInterpreterPython::Locker::FreeAcquiredLock | - ScriptInterpreterPython::Locker::TearDownSession); - - // The following call drops into the embedded interpreter loop and stays there until the - // user chooses to exit from the Python interpreter. - // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before - // a system call that can hang, and lock it when the syscall has returned. - - // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and - // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want - // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off, - // and things could hang (it's happened before). - - StreamString run_string; - run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ()); - PyRun_SimpleString (run_string.GetData()); - - if (is_a_tty) - terminal_state.Restore(); - } - } - SetIsDone(true); - } - - void - Cancel () override - { - - } - - bool - Interrupt () override - { - return m_python->Interrupt(); - } - - void - GotEOF() override - { - - } -protected: - ScriptInterpreterPython *m_python; -}; - - -void -ScriptInterpreterPython::ExecuteInterpreterLoop () -{ - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - Debugger &debugger = GetCommandInterpreter().GetDebugger(); - - // At the moment, the only time the debugger does not have an input file handle is when this is called - // directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to - // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't - // do it. - - if (!debugger.GetInputFile()->GetFile().IsValid()) - return; - - IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this)); - if (io_handler_sp) - { - debugger.PushIOHandler(io_handler_sp); - } -} - -bool -ScriptInterpreterPython::Interrupt() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); - - if (IsExecutingPython()) - { - PyThreadState* state = _PyThreadState_Current; - if (!state) - state = GetThreadState(); - if (state) - { - long tid = state->thread_id; - _PyThreadState_Current = state; - int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); - return true; - } - } - if (log) - log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt"); - return false; - -} -bool -ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, - ScriptInterpreter::ScriptReturnType return_type, - void *ret_value, - const ExecuteScriptOptions &options) -{ - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - - PyObject *py_return = nullptr; - PythonObject &main_module = GetMainModule (); - PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = nullptr; - bool ret_success = false; - int success; - - PythonDictionary locals = GetSessionDictionary (); - - if (!locals) - { - locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str()); - } - - if (!locals) - locals = globals; - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - PyErr_Clear(); - - if (in_string != nullptr) - { - { // scope for PythonInputReaderManager - //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get()); - if (py_return == nullptr) - { - py_error = PyErr_Occurred (); - if (py_error != nullptr) - PyErr_Clear (); - - py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get()); - } - } - - if (py_return != nullptr) - { - switch (return_type) - { - case eScriptReturnTypeCharPtr: // "char *" - { - const char format[3] = "s#"; - success = PyArg_Parse (py_return, format, (char **) ret_value); - break; - } - case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None - { - const char format[3] = "z"; - success = PyArg_Parse (py_return, format, (char **) ret_value); - break; - } - case eScriptReturnTypeBool: - { - const char format[2] = "b"; - success = PyArg_Parse (py_return, format, (bool *) ret_value); - break; - } - case eScriptReturnTypeShortInt: - { - const char format[2] = "h"; - success = PyArg_Parse (py_return, format, (short *) ret_value); - break; - } - case eScriptReturnTypeShortIntUnsigned: - { - const char format[2] = "H"; - success = PyArg_Parse (py_return, format, (unsigned short *) ret_value); - break; - } - case eScriptReturnTypeInt: - { - const char format[2] = "i"; - success = PyArg_Parse (py_return, format, (int *) ret_value); - break; - } - case eScriptReturnTypeIntUnsigned: - { - const char format[2] = "I"; - success = PyArg_Parse (py_return, format, (unsigned int *) ret_value); - break; - } - case eScriptReturnTypeLongInt: - { - const char format[2] = "l"; - success = PyArg_Parse (py_return, format, (long *) ret_value); - break; - } - case eScriptReturnTypeLongIntUnsigned: - { - const char format[2] = "k"; - success = PyArg_Parse (py_return, format, (unsigned long *) ret_value); - break; - } - case eScriptReturnTypeLongLong: - { - const char format[2] = "L"; - success = PyArg_Parse (py_return, format, (long long *) ret_value); - break; - } - case eScriptReturnTypeLongLongUnsigned: - { - const char format[2] = "K"; - success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value); - break; - } - case eScriptReturnTypeFloat: - { - const char format[2] = "f"; - success = PyArg_Parse (py_return, format, (float *) ret_value); - break; - } - case eScriptReturnTypeDouble: - { - const char format[2] = "d"; - success = PyArg_Parse (py_return, format, (double *) ret_value); - break; - } - case eScriptReturnTypeChar: - { - const char format[2] = "c"; - success = PyArg_Parse (py_return, format, (char *) ret_value); - break; - } - case eScriptReturnTypeOpaqueObject: - { - success = true; - Py_XINCREF(py_return); - *((PyObject**)ret_value) = py_return; - break; - } - } - Py_XDECREF (py_return); - if (success) - ret_success = true; - else - ret_success = false; - } - } - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - { - ret_success = false; - if (options.GetMaskoutErrors()) - { - if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError)) - PyErr_Print (); - PyErr_Clear(); - } - } - - return ret_success; -} - -Error -ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options) -{ - Error error; - - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, - ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - - PythonObject return_value; - PythonObject &main_module = GetMainModule (); - PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = nullptr; - - PythonDictionary locals = GetSessionDictionary (); - - if (!locals) - { - locals = PyObject_GetAttrString (globals.get(), m_dictionary_name.c_str()); - } - - if (!locals) - { - locals = globals; - } - - py_error = PyErr_Occurred(); - if (py_error != nullptr) - PyErr_Clear(); - - if (in_string != nullptr) - { - struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input); - if (compiled_node) - { - PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py"); - if (compiled_code) - { - return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get())); - } - } - } - - py_error = PyErr_Occurred (); - if (py_error != nullptr) - { -// puts(in_string); -// _PyObject_Dump (py_error); -// PyErr_Print(); -// success = false; - - PyObject *type = nullptr; - PyObject *value = nullptr; - PyObject *traceback = nullptr; - PyErr_Fetch (&type,&value,&traceback); - - // get the backtrace - std::string bt = ReadPythonBacktrace(traceback); - - if (value && value != Py_None) - error.SetErrorStringWithFormat("%s\n%s", PyString_AsString(PyObject_Str(value)),bt.c_str()); - else - error.SetErrorStringWithFormat("%s",bt.c_str()); - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - if (options.GetMaskoutErrors()) - { - PyErr_Clear(); - } - } - - return error; -} - - -void -ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector &bp_options_vec, - CommandReturnObject &result) -{ - m_active_io_handler = eIOHandlerBreakpoint; - m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec); -} - -void -ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, - CommandReturnObject &result) -{ - m_active_io_handler = eIOHandlerWatchpoint; - m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options); -} - -void -ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, - const char *function_name) -{ - // For now just cons up a oneliner that calls the provided function. - std::string oneliner("return "); - oneliner += function_name; - oneliner += "(frame, bp_loc, internal_dict)"; - m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, - oneliner.c_str()); -} - -// Set a Python one-liner as the callback for the breakpoint. -Error -ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *command_body_text) -{ - std::unique_ptr data_ap(new BreakpointOptions::CommandData()); - - // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will - // wrap the body in an auto-generated function, and return the function name in script_source. That is what - // the callback will actually invoke. - - data_ap->user_source.SplitIntoLines(command_body_text); - Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source); - if (error.Success()) - { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); - return error; - } - else - return error; -} - -// Set a Python one-liner as the callback for the watchpoint. -void -ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options, - const char *oneliner) -{ - std::unique_ptr data_ap(new WatchpointOptions::CommandData()); - - // It's necessary to set both user_source and script_source to the oneliner. - // The former is used to generate callback description (as in watchpoint command list) - // while the latter is used for Python to interpret during the actual callback. - - data_ap->user_source.AppendString (oneliner); - data_ap->script_source.assign (oneliner); - - if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) - { - BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); - wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); - } - - return; -} - -Error -ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) -{ - // Convert StringList to one long, newline delimited, const char *. - std::string function_def_string(function_def.CopyList()); - - Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); - return error; -} - -Error -ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) -{ - Error error; - int num_lines = input.GetSize (); - if (num_lines == 0) - { - error.SetErrorString ("No input data."); - return error; - } - - if (!signature || *signature == 0) - { - error.SetErrorString("No output function name."); - return error; - } - - StreamString sstr; - StringList auto_generated_function; - auto_generated_function.AppendString (signature); - auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary - auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict - auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict - auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the - // global dictionary. - - // Wrap everything up inside the function, increasing the indentation. - - auto_generated_function.AppendString(" if True:"); - for (int i = 0; i < num_lines; ++i) - { - sstr.Clear (); - sstr.Printf (" %s", input.GetStringAtIndex (i)); - auto_generated_function.AppendString (sstr.GetData()); - } - auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict - auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values - auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict - auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict - - // Verify that the results are valid Python. - - error = ExportFunctionDefinitionToInterpreter (auto_generated_function); - - return error; -} - -bool -ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the - // ValueObject as parameter to the function. - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); - sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(), user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - -bool -ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions)); - - sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(),user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - - -bool -ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token) -{ - static uint32_t num_created_classes = 0; - user_input.RemoveBlankLines (); - int num_lines = user_input.GetSize (); - StreamString sstr; - - // Check to see if we have any data; if not, just return. - if (user_input.GetSize() == 0) - return false; - - // Wrap all user input into a Python class - - std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token)); - - StringList auto_generated_class; - - // Create the function name & definition string. - - sstr.Printf ("class %s:", auto_generated_class_name.c_str()); - auto_generated_class.AppendString (sstr.GetData()); - - // Wrap everything up inside the class, increasing the indentation. - // we don't need to play any fancy indentation tricks here because there is no - // surrounding code whose indentation we need to honor - for (int i = 0; i < num_lines; ++i) - { - sstr.Clear (); - sstr.Printf (" %s", user_input.GetStringAtIndex (i)); - auto_generated_class.AppendString (sstr.GetData()); - } - - - // Verify that the results are valid Python. - // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported) - // (TODO: rename that method to ExportDefinitionToInterpreter) - if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success()) - return false; - - // Store the name of the auto-generated class - - output.assign(auto_generated_class_name); - return true; -} - -StructuredData::GenericSP -ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!process_sp) - return StructuredData::GenericSP(); - - void* ret_val; - - { - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = g_swig_create_os_plugin (class_name, - m_dictionary_name.c_str(), - process_sp); - } - - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) -{ - Locker py_lock(this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_register_info"; - - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::DictionarySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonDictionary result_dict(py_return); - return result_dict.CreateStructuredDictionary(); -} - -StructuredData::ArraySP -ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) -{ - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_thread_info"; - - if (!os_plugin_object_sp) - return StructuredData::ArraySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::ArraySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::ArraySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::ArraySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonList ResultList(py_return); - return ResultList.CreateStructuredArray(); -} - -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to -// as the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template -const char *GetPythonValueFormatString(T t) -{ - assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type."); - return nullptr; -} -template <> const char *GetPythonValueFormatString (char *) { return "s"; } -template <> const char *GetPythonValueFormatString (char) { return "b"; } -template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; } -template <> const char *GetPythonValueFormatString (short) { return "h"; } -template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; } -template <> const char *GetPythonValueFormatString (int) { return "i"; } -template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString (long) { return "l"; } -template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; } -template <> const char *GetPythonValueFormatString (long long) { return "L"; } -template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; } -template <> const char *GetPythonValueFormatString (float t) { return "f"; } -template <> const char *GetPythonValueFormatString (double t) { return "d"; } - -StructuredData::StringSP -ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) -{ - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_register_data"; - static char *param_format = const_cast(GetPythonValueFormatString(tid)); - - if (!os_plugin_object_sp) - return StructuredData::StringSP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::StringSP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::StringSP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::StringSP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - PythonString result_string(py_return); - return result_string.CreateStructuredString(); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) -{ - Locker py_lock(this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "create_thread"; - std::string param_format; - param_format += GetPythonValueFormatString(tid); - param_format += GetPythonValueFormatString(context); - - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); - - StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); - if (!generic) - return nullptr; - PyObject *implementor = (PyObject *)generic->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return StructuredData::DictionarySP(); - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return StructuredData::DictionarySP(); - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, ¶m_format[0], tid, context); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - PythonDictionary result_dict(py_return); - return result_dict.CreateStructuredDictionary(); -} - -StructuredData::ObjectSP -ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::ObjectSP(); - - if (!thread_plan_sp.get()) - return StructuredData::ObjectSP(); - - Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = static_cast(script_interpreter); - - if (!script_interpreter) - return StructuredData::ObjectSP(); - - void* ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - - ret_val = g_swig_thread_plan_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - thread_plan_sp); - } - - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); -} - -bool -ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) -{ - bool explains_stop = true; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error); - if (script_error) - return true; - } - return explains_stop; -} - -bool -ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) -{ - bool should_stop = true; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error); - if (script_error) - return true; - } - return should_stop; -} - -lldb::StateType -ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) -{ - bool should_step = false; - StructuredData::Generic *generic = nullptr; - if (implementor_sp) - generic = implementor_sp->GetAsGeneric(); - if (generic) - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error); - if (script_error) - should_step = true; - } - if (should_step) - return lldb::eStateStepping; - else - return lldb::eStateRunning; -} - -StructuredData::ObjectSP -ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) -{ - if (!file_spec.Exists()) - { - error.SetErrorString("no such file"); - return StructuredData::ObjectSP(); - } - - StructuredData::ObjectSP module_sp; - - if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp)) - return module_sp; - - return StructuredData::ObjectSP(); -} - -StructuredData::DictionarySP -ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, - lldb_private::Error &error) -{ - if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get) - return StructuredData::DictionarySP(); - StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); - if (!generic) - return StructuredData::DictionarySP(); - - PyObject *reply_pyobj = nullptr; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - TargetSP target_sp(target->shared_from_this()); - reply_pyobj = (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp); - } - - PythonDictionary py_dict(reply_pyobj); - - return py_dict.CreateStructuredDictionary(); -} - -StructuredData::ObjectSP -ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) -{ - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::ObjectSP(); - - if (!valobj.get()) - return StructuredData::ObjectSP(); - - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return StructuredData::ObjectSP(); - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return StructuredData::ObjectSP(); - - void *ret_val = nullptr; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_synthetic_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - } - - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); -} - -StructuredData::GenericSP -ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name) -{ - DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this()); - - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!debugger_sp.get()) - return StructuredData::GenericSP(); - - void* ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_create_cmd (class_name, - m_dictionary_name.c_str(), - debugger_sp); - } - - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); -} - -bool -ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token) -{ - StringList input; - input.SplitIntoLines(oneliner, strlen(oneliner)); - return GenerateTypeScriptFunction(input, output, name_token); -} - -bool -ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token) -{ - StringList input; - input.SplitIntoLines(oneliner, strlen(oneliner)); - return GenerateTypeSynthClass(input, output, name_token); -} - - -Error -ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - Error error; - if (user_input.GetSize() == 0) - { - error.SetErrorString("No input data."); - return error; - } - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions)); - sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); - - error = GenerateFunction(sstr.GetData(), user_input); - if (!error.Success()) - return error; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return error; -} - -bool -ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output) -{ - static uint32_t num_created_functions = 0; - user_input.RemoveBlankLines (); - StreamString sstr; - - if (user_input.GetSize() == 0) - return false; - - std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions)); - sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); - - if (!GenerateFunction(sstr.GetData(), user_input).Success()) - return false; - - // Store the name of the auto-generated function to be called. - output.assign(auto_generated_function_name); - return true; -} - -bool -ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj, - StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, - std::string &retval) -{ - - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - if (!valobj.get()) - { - retval.assign(""); - return false; - } - - void *old_callee = nullptr; - StructuredData::Generic *generic = nullptr; - if (callee_wrapper_sp) - { - generic = callee_wrapper_sp->GetAsGeneric(); - if (generic) - old_callee = generic->GetValue(); - } - void* new_callee = old_callee; - - bool ret_val; - if (python_function_name && *python_function_name) - { - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - { - TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); - - Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback"); - ret_val = g_swig_typescript_callback (python_function_name, - GetSessionDictionary().get(), - valobj, - &new_callee, - options_sp, - retval); - } - } - } - else - { - retval.assign(""); - return false; - } - - if (new_callee && old_callee != new_callee) - callee_wrapper_sp.reset(new StructuredPythonObject(new_callee)); - - return ret_val; -} - -void -ScriptInterpreterPython::Clear () -{ - // Release any global variables that might have strong references to - // LLDB objects when clearing the python script interpreter. - Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock, - ScriptInterpreterPython::Locker::FreeAcquiredLock); - - // This may be called as part of Py_Finalize. In that case the modules are destroyed in random - // order and we can't guarantee that we can access these. - if (Py_IsInitialized()) - PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None"); -} - -bool -ScriptInterpreterPython::BreakpointCallbackFunction -( - void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id -) -{ - BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton; - const char *python_function_name = bp_option_data->script_source.c_str(); - - if (!context) - return true; - - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return true; - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return true; - - if (python_function_name && python_function_name[0]) - { - const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); - BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id); - if (breakpoint_sp) - { - const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id)); - - if (stop_frame_sp && bp_loc_sp) - { - bool ret_val = true; - { - Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_breakpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - bp_loc_sp); - } - return ret_val; - } - } - } - // We currently always true so we stop in case anything goes wrong when - // trying to call the script function - return true; -} - -bool -ScriptInterpreterPython::WatchpointCallbackFunction -( - void *baton, - StoppointCallbackContext *context, - user_id_t watch_id -) -{ - WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton; - const char *python_function_name = wp_option_data->script_source.c_str(); - - if (!context) - return true; - - ExecutionContext exe_ctx (context->exe_ctx_ref); - Target *target = exe_ctx.GetTargetPtr(); - - if (!target) - return true; - - Debugger &debugger = target->GetDebugger(); - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; - - if (!script_interpreter) - return true; - - if (python_function_name && python_function_name[0]) - { - const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); - WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id); - if (wp_sp) - { - if (stop_frame_sp && wp_sp) - { - bool ret_val = true; - { - Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_watchpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - wp_sp); - } - return ret_val; - } - } - } - // We currently always true so we stop in case anything goes wrong when - // trying to call the script function - return true; -} - -size_t -ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp) -{ - if (!implementor_sp) - return 0; - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return 0; - void *implementor = generic->GetValue(); - if (!implementor) - return 0; - - if (!g_swig_calc_children) - return 0; - - size_t ret_val = 0; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_calc_children (implementor); - } - - return ret_val; -} - -lldb::ValueObjectSP -ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx) -{ - if (!implementor_sp) - return lldb::ValueObjectSP(); - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return lldb::ValueObjectSP(); - void *implementor = generic->GetValue(); - if (!implementor) - return lldb::ValueObjectSP(); - - if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) - return lldb::ValueObjectSP(); - - lldb::ValueObjectSP ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void* child_ptr = g_swig_get_child_index (implementor,idx); - if (child_ptr != nullptr && child_ptr != Py_None) - { - lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); - if (sb_value_ptr == nullptr) - Py_XDECREF(child_ptr); - else - ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); - } - else - { - Py_XDECREF(child_ptr); - } - } - - return ret_val; -} - -int -ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name) -{ - if (!implementor_sp) - return UINT32_MAX; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return UINT32_MAX; - void *implementor = generic->GetValue(); - if (!implementor) - return UINT32_MAX; - - if (!g_swig_get_index_child) - return UINT32_MAX; - - int ret_val = UINT32_MAX; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_get_index_child (implementor, child_name); - } - - return ret_val; -} - -bool -ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) -{ - bool ret_val = false; - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_update_provider) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_update_provider (implementor); - } - - return ret_val; -} - -bool -ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) -{ - bool ret_val = false; - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_mighthavechildren_provider) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_mighthavechildren_provider (implementor); - } - - return ret_val; -} - -lldb::ValueObjectSP -ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp) -{ - lldb::ValueObjectSP ret_val(nullptr); - - if (!implementor_sp) - return ret_val; - - StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); - if (!generic) - return ret_val; - void *implementor = generic->GetValue(); - if (!implementor) - return ret_val; - - if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) - return ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - void* child_ptr = g_swig_getvalue_provider (implementor); - if (child_ptr != nullptr && child_ptr != Py_None) - { - lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); - if (sb_value_ptr == nullptr) - Py_XDECREF(child_ptr); - else - ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); - } - else - { - Py_XDECREF(child_ptr); - } - } - - return ret_val; -} - -static std::string -ReadPythonBacktrace (PyObject* py_backtrace) -{ - PyObject* traceback_module = nullptr, - *stringIO_module = nullptr, - *stringIO_builder = nullptr, - *stringIO_buffer = nullptr, - *printTB = nullptr, - *printTB_args = nullptr, - *printTB_result = nullptr, - *stringIO_getvalue = nullptr, - *printTB_string = nullptr; - - std::string retval("backtrace unavailable"); - - if (py_backtrace && py_backtrace != Py_None) - { - traceback_module = PyImport_ImportModule("traceback"); - stringIO_module = PyImport_ImportModule("StringIO"); - - if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None) - { - stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO"); - if (stringIO_builder && stringIO_builder != Py_None) - { - stringIO_buffer = PyObject_CallObject(stringIO_builder, nullptr); - if (stringIO_buffer && stringIO_buffer != Py_None) - { - printTB = PyObject_GetAttrString(traceback_module, "print_tb"); - if (printTB && printTB != Py_None) - { - printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer); - printTB_result = PyObject_CallObject(printTB, printTB_args); - stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue"); - if (stringIO_getvalue && stringIO_getvalue != Py_None) - { - printTB_string = PyObject_CallObject (stringIO_getvalue,nullptr); - if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string)) - retval.assign(PyString_AsString(printTB_string)); - } - } - } - } - } - } - Py_XDECREF(traceback_module); - Py_XDECREF(stringIO_module); - Py_XDECREF(stringIO_builder); - Py_XDECREF(stringIO_buffer); - Py_XDECREF(printTB); - Py_XDECREF(printTB_args); - Py_XDECREF(printTB_result); - Py_XDECREF(stringIO_getvalue); - Py_XDECREF(printTB_string); - return retval; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Process* process, - std::string& output, - Error& error) -{ - bool ret_val; - if (!process) - { - error.SetErrorString("no process"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_process) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ProcessSP process_sp(process->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Thread* thread, - std::string& output, - Error& error) -{ - bool ret_val; - if (!thread) - { - error.SetErrorString("no thread"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_thread) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ThreadSP thread_sp(thread->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - Target* target, - std::string& output, - Error& error) -{ - bool ret_val; - if (!target) - { - error.SetErrorString("no thread"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_target) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - TargetSP target_sp(target->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - StackFrame* frame, - std::string& output, - Error& error) -{ - bool ret_val; - if (!frame) - { - error.SetErrorString("no frame"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_frame) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - StackFrameSP frame_sp(frame->shared_from_this()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, - ValueObject *value, - std::string& output, - Error& error) -{ - bool ret_val; - if (!value) - { - error.SetErrorString("no value"); - return false; - } - if (!impl_function || !impl_function[0]) - { - error.SetErrorString("no function to execute"); - return false; - } - if (!g_swig_run_script_keyword_value) - { - error.SetErrorString("internal helper function missing"); - return false; - } - { - ValueObjectSP value_sp(value->GetSP()); - Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output); - if (!ret_val) - error.SetErrorString("python script evaluation failed"); - } - return ret_val; -} - -uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr) -{ - size_t pos = 0; - uint64_t matches = 0; - while((pos = str.find(oldStr, pos)) != std::string::npos) - { - matches++; - str.replace(pos, oldStr.length(), newStr); - pos += newStr.length(); - } - return matches; -} - -bool -ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error, - StructuredData::ObjectSP *module_sp) -{ - if (!pathname || !pathname[0]) - { - error.SetErrorString("invalid pathname"); - return false; - } - - if (!g_swig_call_module_init) - { - error.SetErrorString("internal helper function missing"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - - { - FileSpec target_file(pathname, true); - std::string basename(target_file.GetFilename().GetCString()); - - StreamString command_stream; - - // Before executing Pyton code, lock the GIL. - Locker py_lock (this, - Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, - Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); - - if (target_file.GetFileType() == FileSpec::eFileTypeInvalid || - target_file.GetFileType() == FileSpec::eFileTypeUnknown) - { - // if not a valid file of any sort, check if it might be a filename still - // dot can't be used but / and \ can, and if either is found, reject - if (strchr(pathname,'\\') || strchr(pathname,'/')) - { - error.SetErrorString("invalid pathname"); - return false; - } - basename = pathname; // not a filename, probably a package of some sort, let it go through - } - else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory || - target_file.GetFileType() == FileSpec::eFileTypeRegular || - target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink) - { - std::string directory(target_file.GetDirectory().GetCString()); - replace_all(directory,"'","\\'"); - - // now make sure that Python has "directory" in the search path - StreamString command_stream; - command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n", - directory.c_str(), - directory.c_str()); - bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success(); - if (!syspath_retval) - { - error.SetErrorString("Python sys.path handling failed"); - return false; - } - - // strip .py or .pyc extension - ConstString extension = target_file.GetFileNameExtension(); - if (extension) - { - if (::strcmp(extension.GetCString(), "py") == 0) - basename.resize(basename.length()-3); - else if(::strcmp(extension.GetCString(), "pyc") == 0) - basename.resize(basename.length()-4); - } - } - else - { - error.SetErrorString("no known way to import this module specification"); - return false; - } - - // check if the module is already import-ed - command_stream.Clear(); - command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str()); - bool does_contain = false; - // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process - // in which this LLDB framework is living - bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(), - ScriptInterpreterPython::eScriptReturnTypeBool, - &does_contain, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain); - // this call will fail if the module was not imported in this Debugger before - command_stream.Clear(); - command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); - bool was_imported_locally = !(GetSessionDictionary().GetItemForKey(basename.c_str()).IsNULLOrNone()); - - bool was_imported = (was_imported_globally || was_imported_locally); - - if (was_imported == true && can_reload == false) - { - error.SetErrorString("module already imported"); - return false; - } - - // now actually do the import - command_stream.Clear(); - - if (was_imported) - { - if (!was_imported_locally) - command_stream.Printf("import %s ; reload(%s)",basename.c_str(),basename.c_str()); - else - command_stream.Printf("reload(%s)",basename.c_str()); - } - else - command_stream.Printf("import %s",basename.c_str()); - - error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)); - if (error.Fail()) - return false; - - // if we are here, everything worked - // call __lldb_init_module(debugger,dict) - if (!g_swig_call_module_init (basename.c_str(), - m_dictionary_name.c_str(), - debugger_sp)) - { - error.SetErrorString("calling __lldb_init_module failed"); - return false; - } - - if (module_sp) - { - // everything went just great, now set the module object - command_stream.Clear(); - command_stream.Printf("%s",basename.c_str()); - void* module_pyobj = nullptr; - if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj) - module_sp->reset(new StructuredPythonObject(module_pyobj)); - } - - return true; - } -} - -bool -ScriptInterpreterPython::IsReservedWord (const char* word) -{ - if (!word || !word[0]) - return false; - - llvm::StringRef word_sr(word); - - // filter out a few characters that would just confuse us - // and that are clearly not keyword material anyway - if (word_sr.find_first_of("'\"") != llvm::StringRef::npos) - return false; - - StreamString command_stream; - command_stream.Printf("keyword.iskeyword('%s')", word); - bool result; - ExecuteScriptOptions options; - options.SetEnableIO(false); - options.SetMaskoutErrors(true); - options.SetSetLLDBGlobals(false); - if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options)) - return result; - return false; -} - -ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp, - ScriptedCommandSynchronicity synchro) : - m_debugger_sp(debugger_sp), - m_synch_wanted(synchro), - m_old_asynch(debugger_sp->GetAsyncExecution()) -{ - if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous) - m_debugger_sp->SetAsyncExecution(false); - else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous) - m_debugger_sp->SetAsyncExecution(true); -} - -ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() -{ - if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) - m_debugger_sp->SetAsyncExecution(m_old_asynch); -} - -bool -ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) -{ - if (!impl_function) - { - error.SetErrorString("no function to execute"); - return false; - } - - if (!g_swig_call_command) - { - error.SetErrorString("no helper function to run scripted commands"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); - - if (!debugger_sp.get()) - { - error.SetErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - std::string err_msg; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), - Locker::FreeLock | Locker::TearDownSession); - - SynchronicityHandler synch_handler(debugger_sp, - synchronicity); - - ret_val = g_swig_call_command (impl_function, - m_dictionary_name.c_str(), - debugger_sp, - args, - cmd_retobj, - exe_ctx_ref_sp); - } - - if (!ret_val) - error.SetErrorString("unable to execute script function"); - else - error.Clear(); - - return ret_val; -} - -bool -ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, - const char* args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject& cmd_retobj, - Error& error, - const lldb_private::ExecutionContext& exe_ctx) -{ - if (!impl_obj_sp || !impl_obj_sp->IsValid()) - { - error.SetErrorString("no function to execute"); - return false; - } - - if (!g_swig_call_command_object) - { - error.SetErrorString("no helper function to run scripted commands"); - return false; - } - - lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); - lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); - - if (!debugger_sp.get()) - { - error.SetErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - std::string err_msg; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), - Locker::FreeLock | Locker::TearDownSession); - - SynchronicityHandler synch_handler(debugger_sp, - synchronicity); - - ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(), - debugger_sp, - args, - cmd_retobj, - exe_ctx_ref_sp); - } - - if (!ret_val) - error.SetErrorString("unable to execute script function"); - else - error.Clear(); - - return ret_val; -} - -// in Python, a special attribute __doc__ contains the docstring -// for an object (function, method, class, ...) if any is defined -// Otherwise, the attribute's value is None -bool -ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest) -{ - dest.clear(); - if (!item || !*item) - return false; - std::string command(item); - command += ".__doc__"; - - char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully - - if (ExecuteOneLineWithReturn (command.c_str(), - ScriptInterpreter::eScriptReturnTypeCharStrOrNone, - &result_ptr, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) - { - if (result_ptr) - dest.assign(result_ptr); - return true; - } - else - { - StreamString str_stream; - str_stream.Printf("Function %s was not found. Containing module might be missing.",item); - dest.assign(str_stream.GetData()); - return false; - } -} - -bool -ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, - std::string& dest) -{ - bool got_string = false; - dest.clear(); - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_short_help"; - - if (!cmd_obj_sp) - return false; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return false; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return false; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return false; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyString_Check(py_return)) - { - dest.assign(PyString_AsString(py_return)); - got_string = true; - } - } - Py_XDECREF(py_return); - - return got_string; -} - -uint32_t -ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) -{ - uint32_t result = 0; - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_flags"; - - if (!cmd_obj_sp) - return result; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return result; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return result; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return result; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyInt_Check(py_return)) - result = (uint32_t)PyInt_AsLong(py_return); - else if (PyLong_Check(py_return)) - result = (uint32_t)PyLong_AsLong(py_return); - } - Py_XDECREF(py_return); - - return result; -} - -bool -ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, - std::string& dest) -{ - bool got_string = false; - dest.clear(); - - Locker py_lock (this, - Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - static char callee_name[] = "get_long_help"; - - if (!cmd_obj_sp) - return false; - - PyObject* implementor = (PyObject*)cmd_obj_sp->GetValue(); - - if (implementor == nullptr || implementor == Py_None) - return false; - - PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - if (pmeth == nullptr || pmeth == Py_None) - { - Py_XDECREF(pmeth); - return false; - } - - if (PyCallable_Check(pmeth) == 0) - { - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - return false; - } - - if (PyErr_Occurred()) - { - PyErr_Clear(); - } - - Py_XDECREF(pmeth); - - // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - if (py_return != nullptr && py_return != Py_None) - { - if (PyString_Check(py_return)) - { - dest.assign(PyString_AsString(py_return)); - got_string = true; - } - } - Py_XDECREF(py_return); - - return got_string; -} - -std::unique_ptr -ScriptInterpreterPython::AcquireInterpreterLock () -{ - std::unique_ptr py_lock(new Locker(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, - Locker::FreeLock | Locker::TearDownSession)); - return py_lock; -} - -void -ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback, - SWIGBreakpointCallbackFunction swig_breakpoint_callback, - SWIGWatchpointCallbackFunction swig_watchpoint_callback, - SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, - SWIGPythonCreateSyntheticProvider swig_synthetic_script, - SWIGPythonCreateCommandObject swig_create_cmd, - SWIGPythonCalculateNumChildren swig_calc_children, - SWIGPythonGetChildAtIndex swig_get_child_index, - SWIGPythonGetIndexOfChildWithName swig_get_index_child, - SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , - SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, - SWIGPythonUpdateSynthProviderInstance swig_update_provider, - SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, - SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, - SWIGPythonCallCommand swig_call_command, - SWIGPythonCallCommandObject swig_call_command_object, - SWIGPythonCallModuleInit swig_call_module_init, - SWIGPythonCreateOSPlugin swig_create_os_plugin, - SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, - SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, - SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, - SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, - SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, - SWIGPython_GetDynamicSetting swig_plugin_get, - SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, - SWIGPythonCallThreadPlan swig_call_thread_plan) -{ - g_swig_init_callback = swig_init_callback; - g_swig_breakpoint_callback = swig_breakpoint_callback; - g_swig_watchpoint_callback = swig_watchpoint_callback; - g_swig_typescript_callback = swig_typescript_callback; - g_swig_synthetic_script = swig_synthetic_script; - g_swig_create_cmd = swig_create_cmd; - g_swig_calc_children = swig_calc_children; - g_swig_get_child_index = swig_get_child_index; - g_swig_get_index_child = swig_get_index_child; - g_swig_cast_to_sbvalue = swig_cast_to_sbvalue; - g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; - g_swig_update_provider = swig_update_provider; - g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; - g_swig_getvalue_provider = swig_getvalue_provider; - g_swig_call_command = swig_call_command; - 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_run_script_keyword_process = swig_run_script_keyword_process; - g_swig_run_script_keyword_thread = swig_run_script_keyword_thread; - g_swig_run_script_keyword_target = swig_run_script_keyword_target; - g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; - g_swig_run_script_keyword_value = swig_run_script_keyword_value; - g_swig_plugin_get = swig_plugin_get; - g_swig_thread_plan_script = swig_thread_plan_script; - g_swig_call_thread_plan = swig_call_thread_plan; -} - -void -ScriptInterpreterPython::InitializePrivate () -{ - assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!"); - g_initialized = true; - - Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - - // Python will muck with STDIN terminal state, so save off any current TTY - // settings so we can restore them. - TerminalState stdin_tty_state; - stdin_tty_state.Save(STDIN_FILENO, false); - -#if defined(LLDB_PYTHON_HOME) - Py_SetPythonHome(LLDB_PYTHON_HOME); -#endif - PyGILState_STATE gstate; - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); - bool threads_already_initialized = false; - if (PyEval_ThreadsInitialized ()) { - gstate = PyGILState_Ensure (); - if (log) - log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : ""); - threads_already_initialized = true; - } else { - // InitThreads acquires the GIL if it hasn't been called before. - PyEval_InitThreads (); - } - Py_InitializeEx (0); - - if (g_swig_init_callback) - g_swig_init_callback (); - - // Update the path python uses to search for modules to include the current directory. - - PyRun_SimpleString ("import sys"); - AddToSysPath(AddLocation::End, "."); - - FileSpec file_spec; - // Don't denormalize paths when calling file_spec.GetPath(). On platforms that use - // a backslash as the path separator, this will result in executing python code containing - // paths with unescaped backslashes. But Python also accepts forward slashes, so to make - // life easier we just use that. - if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) - AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); - if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) - AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); - - PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line"); - - if (threads_already_initialized) { - if (log) - log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : ""); - PyGILState_Release (gstate); - } else { - // We initialized the threads in this function, just unlock the GIL. - PyEval_SaveThread(); - } - - stdin_tty_state.Restore(); -} - -void -ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path) -{ - std::string path_copy; - - std::string statement; - if (location == AddLocation::Beginning) - { - statement.assign("sys.path.insert(0,\""); - statement.append (path); - statement.append ("\")"); - } - else - { - statement.assign("sys.path.append(\""); - statement.append(path); - statement.append("\")"); - } - PyRun_SimpleString (statement.c_str()); -} - - -//void -//ScriptInterpreterPython::Terminate () -//{ -// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling -// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers -// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls -// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate, -// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls -// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from -// // within Py_Finalize, which results in a seg fault. -// // -// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't -// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the -// // process exits). -// // -//// Py_Finalize (); -//} - -#endif // #ifdef LLDB_DISABLE_PYTHON diff --git a/source/Interpreter/embedded_interpreter.py b/source/Interpreter/embedded_interpreter.py index 10186f5a9d50..8ba539a2b0c9 100644 --- a/source/Interpreter/embedded_interpreter.py +++ b/source/Interpreter/embedded_interpreter.py @@ -1,7 +1,10 @@ -import __builtin__ +import sys +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins import code import lldb -import sys import traceback try: @@ -42,8 +45,8 @@ def setquit(): # "sys.exit(123)" global g_builtin_override_called g_builtin_override_called = False - __builtin__.quit = LLDBQuitter('quit') - __builtin__.exit = LLDBQuitter('exit') + builtins.quit = LLDBQuitter('quit') + builtins.exit = LLDBQuitter('exit') # When running one line, we might place the string to run in this string # in case it would be hard to correctly escape a string's contents @@ -94,7 +97,7 @@ def run_python_interpreter (local_dict): except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print 'Script exited with %s' %(e) + print('Script exited with %s' %(e)) def run_one_line (local_dict, input_string): global g_run_one_line_str @@ -109,4 +112,4 @@ def run_one_line (local_dict, input_string): except SystemExit as e: global g_builtin_override_called if not g_builtin_override_called: - print 'Script exited with %s' %(e) + print('Script exited with %s' %(e)) diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 700d223fbc6d..3b9b0f346072 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@ #include "llvm/ADT/Triple.h" #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" #include @@ -38,90 +37,90 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, @@ -239,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, size_t num_stack_regs = ae - ai; sp -= (num_stack_regs * 4); - // Keep the stack 8 byte aligned, not that we need to - sp &= ~(8ull-1ull); + // Keep the stack 16 byte aligned + sp &= ~(16ull-1ull); // just using arg1 to get the right size const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); @@ -333,18 +332,18 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, if (!value) return false; - ClangASTType clang_type = value->GetClangType(); - if (clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (compiler_type) { bool is_signed = false; size_t bit_width = 0; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } - else if (clang_type.IsPointerOrReferenceType ()) + else if (compiler_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } else { @@ -414,22 +413,37 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, return true; } +bool +ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const +{ + bool is_armv7k = false; + if (thread) + { + ProcessSP process_sp (thread->GetProcess()); + if (process_sp) + { + const ArchSpec &arch (process_sp->GetTarget().GetArchitecture()); + const ArchSpec::Core system_core = arch.GetCore(); + if (system_core == ArchSpec::eCore_arm_armv7k) + { + is_armv7k = true; + } + } + } + return is_armv7k; +} + ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, - lldb_private::ClangASTType &clang_type) const + lldb_private::CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) - return return_valobj_sp; - - clang::ASTContext *ast_context = clang_type.GetASTContext(); - if (!ast_context) + if (!compiler_type) return return_valobj_sp; - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -441,14 +455,68 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); switch (bit_width) { default: return return_valobj_sp; + case 128: + if (IsArmv7kProcess (&thread)) + { + // "A composite type not larger than 16 bytes is returned in r0-r3. The format is + // as if the result had been stored in memory at a word-aligned address and then + // loaded into r0-r3 with an ldm instruction" + { + const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); + const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); + 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); + 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 + && process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue r0_reg_value; + RegisterValue r1_reg_value; + RegisterValue r2_reg_value; + RegisterValue r3_reg_value; + if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value) + && reg_ctx->ReadRegister(r1_reg_info, r1_reg_value) + && reg_ctx->ReadRegister(r2_reg_info, r2_reg_value) + && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value)) + { + Error error; + if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error) + && r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error) + && r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error) + && r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetAddressByteSize()); + + return_valobj_sp = ValueObjectConstResult::Create (&thread, + compiler_type, + ConstString(""), + data); + return return_valobj_sp; + } + } + } + } + } + } + else + { + return return_valobj_sp; + } + break; case 64: { const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); @@ -481,7 +549,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; @@ -510,8 +578,8 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -526,7 +594,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -561,12 +629,45 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj } } } + else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get())) + { + // "A composite type not larger than 16 bytes is returned in r0-r3. The format is + // as if the result had been stored in memory at a word-aligned address and then + // loaded into r0-r3 with an ldm instruction" + + const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); + const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); + const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); + const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); + lldb::offset_t offset = 0; + uint32_t bytes_written = 4; + uint32_t raw_value = data.GetMaxU64(&offset, 4); + if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value)) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value)) + { + set_it_simple = true; + } + } + } + } + } else { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index eee43943d73a..a4e9dead7794 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -20,42 +20,36 @@ class ABIMacOSX_arm : public lldb_private::ABI { public: - ~ABIMacOSX_arm() { } + ~ABIMacOSX_arm() override = default; - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t func_addr, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 4 byte aligned if (cfa & (4ull - 1ull)) @@ -65,8 +59,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // Just make sure the address is a valid 32 bit address. Bit zero // might be set due to Thumb function calls, so don't enforce 2 byte @@ -74,20 +68,24 @@ public: return pc <= UINT32_MAX; } - virtual lldb::addr_t - FixCodeAddress (lldb::addr_t pc) + lldb::addr_t + FixCodeAddress(lldb::addr_t pc) override { // ARM uses bit zero to signify a code address is thumb, so we must // strip bit zero in any code addresses. return pc & ~(lldb::addr_t)1; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + bool + IsArmv7kProcess (lldb_private::Thread *thread) const; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,13 +101,18 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + private: ABIMacOSX_arm() : lldb_private::ABI() @@ -118,4 +121,4 @@ private: } }; -#endif // liblldb_ABIMacOSX_arm_h_ +#endif // liblldb_ABIMacOSX_arm_h_ diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 04b96180deb3..0e6f9d663ae8 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/Value.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -37,12 +36,11 @@ using namespace lldb; using namespace lldb_private; static const char *pluginDesc = "Mac OS X ABI for arm64 targets"; -static const char *pluginShort = "abi.macosx-arm64"; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ====================== { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -77,7 +75,7 @@ static RegisterInfo g_register_infos[] = { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -115,71 +113,71 @@ static RegisterInfo g_register_infos[] = { "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -322,7 +320,7 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const if (!value) return false; - ClangASTType value_type = value->GetClangType(); + CompilerType value_type = value->GetCompilerType(); if (value_type) { bool is_signed = false; @@ -424,7 +422,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO return error; } - ClangASTType return_value_type = new_value_sp->GetClangType(); + CompilerType return_value_type = new_value_sp->GetCompilerType(); if (!return_value_type) { error.SetErrorString ("Null clang type for return value."); @@ -709,7 +707,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) static bool LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, RegisterContext *reg_ctx, - const ClangASTType &value_type, + const CompilerType &value_type, bool is_return_value, // false => parameter, true => return value uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) @@ -724,18 +722,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); Error error; - ClangASTType base_type; + CompilerType base_type; const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type); if (homogeneous_count > 0 && homogeneous_count <= 8) { - printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count); // Make sure we have enough registers if (NSRN < 8 && (8-NSRN) >= homogeneous_count) { if (!base_type) return false; const size_t base_byte_size = base_type.GetByteSize(nullptr); - printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; for (uint32_t i=0; i args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The arm64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -57,9 +57,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -69,8 +68,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { if (pc & (4ull - 1ull)) return false; // Not 4 byte aligned @@ -79,12 +78,13 @@ public: return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -97,28 +97,26 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic(); - virtual lldb_private::ConstString - GetPluginName() + lldb_private::ConstString + GetPluginName() override { return GetPluginNameStatic(); } - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; protected: - virtual lldb::ValueObjectSP + lldb::ValueObjectSP GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; + lldb_private::CompilerType &ast_type) const override; private: ABIMacOSX_arm64() : @@ -128,4 +126,4 @@ private: } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_arm64_h_ diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 4204d18769b8..75e5fb1558e6 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -16,13 +16,13 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include @@ -32,16 +32,16 @@ using namespace lldb_private; enum { - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags + ehframe_eax = 0, + ehframe_ecx, + ehframe_edx, + ehframe_ebx, + ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin + ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin + ehframe_esi, + ehframe_edi, + ehframe_eip, + ehframe_eflags }; enum @@ -82,121 +82,60 @@ enum dwarf_ymm7 = dwarf_xmm7 }; -enum -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fctrl = 24, gdb_fcw = gdb_fctrl, - gdb_fstat = 25, gdb_fsw = gdb_fstat, - gdb_ftag = 26, gdb_ftw = gdb_ftag, - gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 28, gdb_ip = gdb_fioff, - gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 30, gdb_dp = gdb_fooff, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48, - gdb_ymm0 = gdb_xmm0, - gdb_ymm1 = gdb_xmm1, - gdb_ymm2 = gdb_xmm2, - gdb_ymm3 = gdb_xmm3, - gdb_ymm4 = gdb_xmm4, - gdb_ymm5 = gdb_xmm5, - gdb_ymm6 = gdb_xmm6, - gdb_ymm7 = gdb_xmm7 -}; - static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== - { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL} + { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -237,7 +176,7 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch) { static ABISP g_abi_sp; if ((arch.GetTriple().getArch() == llvm::Triple::x86) && - (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS())) + (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS())) { if (!g_abi_sp) g_abi_sp.reset (new ABIMacOSX_i386); @@ -316,184 +255,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, return true; } -bool -ABIMacOSX_i386::PrepareNormalCall (Thread &thread, - addr_t sp, - addr_t func_addr, - addr_t return_addr, - ValueList &args) const -{ - ExecutionContext exe_ctx (thread.shared_from_this()); - RegisterContext *reg_ctx = thread.GetRegisterContext().get(); - if (!reg_ctx) - return false; - - Process *process = exe_ctx.GetProcessPtr(); - Error error; - uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - - // Do the argument layout - - std::vector argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide - - size_t numArgs = args.GetSize(); - size_t index; - - for (index = 0; index < numArgs; ++index) - { - Value *val = args.GetValueAtIndex(index); - - if (!val) - return false; - - switch (val->GetValueType()) - { - case Value::eValueTypeScalar: - { - Scalar &scalar = val->GetScalar(); - switch (scalar.GetType()) - { - case Scalar::e_void: - return false; - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - { - uint64_t data = scalar.ULongLong(); - - switch (scalar.GetByteSize()) - { - default: - return false; - case 1: - argLayout.push_back((uint32_t)(data & 0xffull)); - break; - case 2: - argLayout.push_back((uint32_t)(data & 0xffffull)); - break; - case 4: - argLayout.push_back((uint32_t)(data & 0xffffffffull)); - break; - case 8: - argLayout.push_back((uint32_t)(data & 0xffffffffull)); - argLayout.push_back((uint32_t)(data >> 32)); - break; - } - } - break; - case Scalar::e_float: - { - float data = scalar.Float(); - uint32_t dataRaw = *((uint32_t*)(&data)); - argLayout.push_back(dataRaw); - } - break; - case Scalar::e_double: - { - double data = scalar.Double(); - uint32_t *dataRaw = ((uint32_t*)(&data)); - argLayout.push_back(dataRaw[0]); - argLayout.push_back(dataRaw[1]); - } - break; - case Scalar::e_long_double: - { - long double data = scalar.Double(); - uint32_t *dataRaw = ((uint32_t*)(&data)); - while ((argLayout.size() * 4) & 0xf) - argLayout.push_back(0); - argLayout.push_back(dataRaw[0]); - argLayout.push_back(dataRaw[1]); - argLayout.push_back(dataRaw[2]); - argLayout.push_back(dataRaw[3]); - } - break; - } - } - break; - case Value::eValueTypeHostAddress: - { - ClangASTType clang_type (val->GetClangType()); - if (clang_type) - { - uint32_t cstr_length = 0; - if (clang_type.IsCStringType (cstr_length)) - { - const char *cstr = (const char*)val->GetScalar().ULongLong(); - cstr_length = strlen(cstr); - - // Push the string onto the stack immediately. - - sp -= (cstr_length + 1); - - if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1)) - return false; - - // Put the address of the string into the argument array. - - argLayout.push_back((uint32_t)(sp & 0xffffffff)); - } - else - { - return false; - } - } - break; - } - break; - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - default: - return false; - } - } - - // Make room for the arguments on the stack - - sp -= 4 * argLayout.size(); - - // Align the SP - - sp &= ~(16ull-1ull); // 16-byte alignment - - // Write the arguments on the stack - - size_t numChunks = argLayout.size(); - - for (index = 0; index < numChunks; ++index) - if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t)) - return false; - - // The return address is pushed onto the stack. - - sp -= 4; - uint32_t returnAddressU32 = return_addr; - if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32)) - return false; - - // %esp is set to the actual stack value. - - if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) - return false; - - // %ebp is set to a fake value, in our case 0x0x00000000 - - if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000)) - return false; - - // %eip is set to the address of the called function. - - if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) - return false; - - return true; -} - static bool ReadIntegerArgument (Scalar &scalar, unsigned int bit_width, @@ -545,23 +306,23 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type (value->GetClangType()); - if (clang_type) + CompilerType compiler_type (value->GetCompilerType()); + if (compiler_type) { bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } - else if (clang_type.IsPointerType()) + else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); @@ -582,8 +343,8 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -598,7 +359,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -638,7 +399,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); @@ -654,16 +415,16 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, - ClangASTType &clang_type) const + CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) + if (!compiler_type) return return_valobj_sp; - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -671,9 +432,9 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -713,7 +474,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index d81b7a7e684b..6a82fce35bf7 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -22,48 +22,33 @@ class ABIMacOSX_i386 : public lldb_private::ABI { public: - - ~ABIMacOSX_i386() { } - - virtual size_t - GetRedZoneSize () const; + ~ABIMacOSX_i386() override = default; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t return_addr, - llvm::ArrayRef args) const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareNormalCall (lldb_private::Thread &thread, + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t func_addr, lldb::addr_t return_addr, - lldb_private::ValueList &args) const; + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The Darwin i386 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // // If we were to enforce 16-byte alignment, we also need to relax to 4-byte // alignment for non-darwin i386 targets. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 4 byte aligned if (cfa & (4ull - 1ull)) @@ -89,19 +74,20 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // Just make sure the address is a valid 32 bit address. return pc <= UINT32_MAX; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -114,22 +100,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic (); - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead. + ABIMacOSX_i386() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; - -#endif // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_i386_h_ diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index 50a9863d83e7..ef625dece265 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@ #include "llvm/ADT/Triple.h" #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" #include @@ -38,90 +37,90 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, @@ -333,18 +332,18 @@ ABISysV_arm::GetArgumentValues (Thread &thread, if (!value) return false; - ClangASTType clang_type = value->GetClangType(); - if (clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (compiler_type) { bool is_signed = false; size_t bit_width = 0; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } - else if (clang_type.IsPointerOrReferenceType ()) + else if (compiler_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } else { @@ -398,22 +397,35 @@ ABISysV_arm::GetArgumentValues (Thread &thread, return true; } +static bool +GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t byte_size, Value& value) +{ + Error error; + DataBufferHeap buffer(byte_size, 0); + + const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error); + + if (error.Fail()) + return false; + + value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); + return true; +} + ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, - lldb_private::ClangASTType &clang_type) const + lldb_private::CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) + if (!compiler_type) return return_valobj_sp; - clang::ASTContext *ast_context = clang_type.GetASTContext(); - if (!ast_context) - return return_valobj_sp; - - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -427,9 +439,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { switch (bit_width) { @@ -467,12 +479,33 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } - else if (clang_type.IsFloatingPointType(float_count, is_complex)) + else if (compiler_type.IsVectorType(nullptr, nullptr)) + { + size_t byte_size = compiler_type.GetByteSize(&thread); + 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) + { + 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); + } + else + { + 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) { @@ -506,9 +539,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, return return_valobj_sp; } } - else if (clang_type.IsAggregateType()) + else if (compiler_type.IsAggregateType()) { - size_t byte_size = clang_type.GetByteSize(&thread); + size_t byte_size = compiler_type.GetByteSize(&thread); if (byte_size <= 4) { RegisterValue r0_reg_value; @@ -517,16 +550,7 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, } else { - RegisterValue r0_reg_value; - uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; - - Error error; - DataBufferHeap buffer(byte_size, 0); - thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error); - - if (error.Success()) - value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); - else + if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) return return_valobj_sp; } } @@ -554,8 +578,8 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -570,7 +594,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -610,7 +634,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index 69becd6ec0c2..e3b280296a64 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -20,7 +20,7 @@ class ABISysV_arm : public lldb_private::ABI { public: - ~ABISysV_arm() { } + ~ABISysV_arm() override = default; size_t GetRedZoneSize () const override; @@ -39,12 +39,6 @@ public: lldb_private::Error SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const override; - -public: bool CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -88,6 +82,7 @@ public: //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,6 +98,7 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; @@ -110,6 +106,10 @@ public: GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + private: ABISysV_arm() : lldb_private::ABI() @@ -118,4 +118,4 @@ private: } }; -#endif // liblldb_ABISysV_arm_h_ +#endif // liblldb_ABISysV_arm_h_ diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index ed058ff19d99..bc6df235cb1e 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -18,7 +18,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -37,7 +36,7 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ====================== { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -313,7 +312,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const if (!value) return false; - ClangASTType value_type = value->GetClangType(); + CompilerType value_type = value->GetCompilerType(); if (value_type) { bool is_signed = false; @@ -397,7 +396,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType return_value_type = new_value_sp->GetClangType(); + CompilerType return_value_type = new_value_sp->GetCompilerType(); if (!return_value_type) { error.SetErrorString ("Null clang type for return value."); @@ -686,7 +685,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) static bool LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, RegisterContext *reg_ctx, - const ClangASTType &value_type, + const CompilerType &value_type, bool is_return_value, // false => parameter, true => return value uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) @@ -701,18 +700,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); Error error; - ClangASTType base_type; + CompilerType base_type; const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type); if (homogeneous_count > 0 && homogeneous_count <= 8) { - printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count); // Make sure we have enough registers if (NSRN < 8 && (8-NSRN) >= homogeneous_count) { if (!base_type) return false; const size_t base_byte_size = base_type.GetByteSize(nullptr); - printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; for (uint32_t i=0; iConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + if (ra_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_reg == LLDB_INVALID_REGNUM) + return false; + // push host data onto target for ( size_t i = 0; i < args.size( ); i++ ) { @@ -277,11 +293,6 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, // check if this is a variable argument function bool isVArg = prototype.isFunctionVarArg(); - // get the register context for modifying all of the registers - RegisterContext *reg_ctx = thread.GetRegisterContext().get(); - if (!reg_ctx) - return false; - // number of arguments passed by register int nRegArgs = nVArgRegParams; if (! isVArg ) @@ -324,10 +335,9 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, } // update registers with current function call state - reg_ctx->WriteRegisterFromUnsigned ( 41, pc ); - reg_ctx->WriteRegisterFromUnsigned ( 31, ra ); - reg_ctx->WriteRegisterFromUnsigned ( 29, sp ); -// reg_ctx->WriteRegisterFromUnsigned ( FP ??? ); + reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); + reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); + reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); #if HEX_ABI_DEBUG // quick and dirty stack dumper for debugging @@ -359,14 +369,14 @@ ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::Valu } ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, CompilerType &return_compiler_type ) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, CompilerType &return_compiler_type ) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 1550a38c4f3b..337e3fdcf7b5 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -21,63 +21,54 @@ class ABISysV_hexagon : public lldb_private::ABI { public: + ~ABISysV_hexagon() override = default; - ~ABISysV_hexagon( void ) - { - } - - virtual size_t - GetRedZoneSize ( void ) const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall ( lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args ) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; // special thread plan for GDB style non-jit function calls - virtual bool - PrepareTrivialCall ( lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::Type &prototype, - llvm::ArrayRef args ) const; - - virtual bool - GetArgumentValues ( lldb_private::Thread &thread, - lldb_private::ValueList &values ) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef args) const override; + + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject ( lldb::StackFrameSP &frame_sp, - lldb::ValueObjectSP &new_value ); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple ( lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type ) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl ( lldb_private::Thread &thread, - lldb_private::ClangASTType &type ) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; // specialized to work with llvm IR types - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &type ) const; + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, llvm::Type &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info ); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid ( lldb::addr_t cfa ) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & 0x07) @@ -87,50 +78,60 @@ public: return true; } - virtual bool - CodeAddressIsValid ( lldb::addr_t pc ) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray ( uint32_t &count ); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void - Initialize ( void ); + Initialize(); static void - Terminate ( void ); + Terminate(); static lldb::ABISP CreateInstance ( const lldb_private::ArchSpec &arch ); static lldb_private::ConstString - GetPluginNameStatic ( void ); + GetPluginNameStatic(); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName ( void ); - virtual uint32_t - GetPluginVersion ( void ); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void - CreateRegisterMapIfNeeded ( void ); + CreateRegisterMapIfNeeded(); + + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_hexagon() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABISysV_hexagon_h_ +#endif // liblldb_ABISysV_hexagon_h_ diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 26da9aeb370d..0a3779a2ce94 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -59,171 +58,109 @@ using namespace lldb_private; // Comment: Table 2.14 is followed till 'mm' entries. // After that, all entries are ignored here. -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_eax = 0, - gcc_dwarf_ecx, - gcc_dwarf_edx, - gcc_dwarf_ebx, - gcc_dwarf_esp, - gcc_dwarf_ebp, - gcc_dwarf_esi, - gcc_dwarf_edi, - gcc_dwarf_eip, - gcc_dwarf_eflags, - - gcc_dwarf_st0 = 11, - gcc_dwarf_st1, - gcc_dwarf_st2, - gcc_dwarf_st3, - gcc_dwarf_st4, - gcc_dwarf_st5, - gcc_dwarf_st6, - gcc_dwarf_st7, - - gcc_dwarf_xmm0 = 21, - gcc_dwarf_xmm1, - gcc_dwarf_xmm2, - gcc_dwarf_xmm3, - gcc_dwarf_xmm4, - gcc_dwarf_xmm5, - gcc_dwarf_xmm6, - gcc_dwarf_xmm7, - gcc_dwarf_ymm0 = gcc_dwarf_xmm0, - gcc_dwarf_ymm1 = gcc_dwarf_xmm1, - gcc_dwarf_ymm2 = gcc_dwarf_xmm2, - gcc_dwarf_ymm3 = gcc_dwarf_xmm3, - gcc_dwarf_ymm4 = gcc_dwarf_xmm4, - gcc_dwarf_ymm5 = gcc_dwarf_xmm5, - gcc_dwarf_ymm6 = gcc_dwarf_xmm6, - gcc_dwarf_ymm7 = gcc_dwarf_xmm7, - - gcc_dwarf_mm0 = 29, - gcc_dwarf_mm1, - gcc_dwarf_mm2, - gcc_dwarf_mm3, - gcc_dwarf_mm4, - gcc_dwarf_mm5, - gcc_dwarf_mm6, - gcc_dwarf_mm7 -}; - - -enum gdb_regnums -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_st0 = 16, - gdb_st1 = 17, - gdb_st2 = 18, - gdb_st3 = 19, - gdb_st4 = 20, - gdb_st5 = 21, - gdb_st6 = 22, - gdb_st7 = 23, - gdb_fctrl = 24, gdb_fcw = gdb_fctrl, - gdb_fstat = 25, gdb_fsw = gdb_fstat, - gdb_ftag = 26, gdb_ftw = gdb_ftag, - gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 28, gdb_ip = gdb_fioff, - gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 30, gdb_dp = gdb_fooff, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48, - gdb_ymm0 = gdb_xmm0, - gdb_ymm1 = gdb_xmm1, - gdb_ymm2 = gdb_xmm2, - gdb_ymm3 = gdb_xmm3, - gdb_ymm4 = gdb_xmm4, - gdb_ymm5 = gdb_xmm5, - gdb_ymm6 = gdb_xmm6, - gdb_ymm7 = gdb_xmm7 + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + + dwarf_st0 = 11, + dwarf_st1, + dwarf_st2, + dwarf_st3, + dwarf_st4, + dwarf_st5, + dwarf_st6, + dwarf_st7, + + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7, + dwarf_ymm0 = dwarf_xmm0, + dwarf_ymm1 = dwarf_xmm1, + dwarf_ymm2 = dwarf_xmm2, + dwarf_ymm3 = dwarf_xmm3, + dwarf_ymm4 = dwarf_xmm4, + dwarf_ymm5 = dwarf_xmm5, + dwarf_ymm6 = dwarf_xmm6, + dwarf_ymm7 = dwarf_xmm7, + + dwarf_mm0 = 29, + dwarf_mm1, + dwarf_mm2, + dwarf_mm3, + dwarf_mm4, + dwarf_mm5, + dwarf_mm6, + dwarf_mm7 }; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== - { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eax , gcc_dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebx , gcc_dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ecx , gcc_dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edx , gcc_dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esi , gcc_dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edi , gcc_dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebp , gcc_dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esp , gcc_dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eip , gcc_dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0 , LLDB_INVALID_REGNUM , gdb_st0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1 , LLDB_INVALID_REGNUM , gdb_st1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2 , LLDB_INVALID_REGNUM , gdb_st2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3 , LLDB_INVALID_REGNUM , gdb_st3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4 , LLDB_INVALID_REGNUM , gdb_st4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5 , LLDB_INVALID_REGNUM , gdb_st5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6 , LLDB_INVALID_REGNUM , gdb_st6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7 , LLDB_INVALID_REGNUM , gdb_st7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr} + { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { dwarf_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { dwarf_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { dwarf_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -387,22 +324,22 @@ ABISysV_i386::GetArgumentValues (Thread &thread, return false; // Currently: Support for extracting values with Clang QualTypes only. - ClangASTType clang_type (value->GetClangType()); - if (clang_type) + CompilerType compiler_type (value->GetCompilerType()); + if (compiler_type) { bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } - else if (clang_type.IsPointerType()) + else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); @@ -418,29 +355,170 @@ Error ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; - //ToDo: Yet to be implemented - error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet"); + if (!new_value_sp) + { + error.SetErrorString("Empty value object for return value."); + return error; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) + { + error.SetErrorString ("Null clang type for return value."); + return error; + } + + const uint32_t type_flags = compiler_type.GetTypeInfo (); + Thread *thread = frame_sp->GetThread().get(); + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + bool register_write_successful = true; + + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + + // Following "IF ELSE" block categorizes various 'Fundamental Data Types'. + // The terminology 'Fundamental Data Types' used here is adopted from + // Table 2.1 of the reference document (specified on top of this file) + + if (type_flags & eTypeIsPointer) // 'Pointer' + { + if(num_bytes != sizeof(uint32_t)) + { + error.SetErrorString("Pointer to be returned is not 4 bytes wide"); + return error; + } + lldb::offset_t offset = 0; + const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + } + else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' + { + lldb::offset_t offset = 0; + const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); + + if (type_flags & eTypeIsInteger) // 'Integral' except enum + { + switch (num_bytes) + { + default: + break; + case 16: + // For clang::BuiltinType::UInt128 & Int128 + // ToDo: Need to decide how to handle it + break; + case 8: + { + uint32_t raw_value_low = data.GetMaxU32(&offset, 4); + const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0); + uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset); + register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) && + reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high)); + break; + } + case 4: + case 2: + case 1: + { + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + break; + } + } + } + else if (type_flags & eTypeIsEnumeration) // handles enum + { + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + } + else if (type_flags & eTypeIsFloat) // 'Floating Point' + { + RegisterValue st0_value, fstat_value, ftag_value; + const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0); + const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0); + const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0); + + /* According to Page 3-12 of document + System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition + To return Floating Point values, all st% registers except st0 should be empty after exiting from + a function. This requires setting fstat and ftag registers to specific values. + fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific + value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */ + uint32_t value_fstat_u32 = 0x00003800; + + /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set + 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance + with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */ + uint32_t value_ftag_u32 = 0x00000080; + + if (num_bytes <= 12) // handles float, double, long double, __float80 + { + long double value_long_dbl = 0.0; + if (num_bytes == 4) + value_long_dbl = data.GetFloat(&offset); + else if (num_bytes == 8) + value_long_dbl = data.GetDouble(&offset); + else if (num_bytes == 12) + value_long_dbl = data.GetLongDouble(&offset); + else + { + error.SetErrorString ("Invalid number of bytes for this return type"); + return error; + } + st0_value.SetLongDouble(value_long_dbl); + fstat_value.SetUInt32(value_fstat_u32); + ftag_value.SetUInt32(value_ftag_u32); + register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) && + reg_ctx->WriteRegister(fstat_info, fstat_value) && + reg_ctx->WriteRegister(ftag_info, ftag_value); + } + else if(num_bytes == 16) // handles __float128 + { + error.SetErrorString ("Implementation is missing for this clang type."); + } + } + else + { + // Neither 'Integral' nor 'Floating Point'. If flow reaches here + // then check type_flags. This type_flags is not a valid type. + error.SetErrorString ("Invalid clang type"); + } + } + else + { + /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types + are yet to be implemented */ + error.SetErrorString ("Currently only Integral and Floating Point clang types are supported."); + } + if(!register_write_successful) + error.SetErrorString ("Register writing failed"); return error; } ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -463,7 +541,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { value.SetValueType(Value::eValueTypeScalar); - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); bool success = false; if (type_flags & eTypeIsInteger) // 'Integral' except enum @@ -579,7 +657,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, nullptr), - return_clang_type); + return_compiler_type); } } @@ -597,16 +675,12 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, else if (type_flags & eTypeIsVector) // 'Packed' { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); + const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); if (vec_reg == nullptr) - { - vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); - if (vec_reg == nullptr) - vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - } + vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); if (vec_reg) { @@ -631,13 +705,52 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } } } } + 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 heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + RegisterValue reg_value2; + if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2)) + { + + Error error; + if (reg_value.GetAsMemoryData (vec_reg, + heap_data_ap->GetBytes(), + vec_reg->byte_size, + byte_order, + error) && + reg_value2.GetAsMemoryData (vec_reg2, + heap_data_ap->GetBytes() + vec_reg->byte_size, + heap_data_ap->GetByteSize() - vec_reg->byte_size, + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + data); + } + } + } + } + } } } } @@ -651,15 +764,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, ValueObjectSP -ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -667,14 +780,14 @@ ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla if (!reg_ctx_sp) return return_valobj_sp; - if (return_clang_type.IsAggregateType()) + if (return_compiler_type.IsAggregateType()) { unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, nullptr), - return_clang_type); + return_compiler_type); } return return_valobj_sp; @@ -690,8 +803,8 @@ ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_esp; - uint32_t pc_reg_num = gcc_dwarf_eip; + uint32_t sp_reg_num = dwarf_esp; + uint32_t pc_reg_num = dwarf_eip; UnwindPlan::RowSP row(new UnwindPlan::Row); row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); @@ -714,9 +827,9 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t fp_reg_num = gcc_dwarf_ebp; - uint32_t sp_reg_num = gcc_dwarf_esp; - uint32_t pc_reg_num = gcc_dwarf_eip; + uint32_t fp_reg_num = dwarf_ebp; + uint32_t sp_reg_num = dwarf_esp; + uint32_t pc_reg_num = dwarf_eip; UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 4; diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h index 9612f900d2ce..2d0f097c328e 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h @@ -21,10 +21,7 @@ class ABISysV_i386 : public lldb_private::ABI { public: - - ~ABISysV_i386() - { - } + ~ABISysV_i386() override = default; size_t GetRedZoneSize () const override @@ -46,18 +43,9 @@ public: lldb_private::Error SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - - bool - RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); - -public: lldb::ValueObjectSP GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const override; + lldb_private::CompilerType &type) const override; bool CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -104,9 +92,11 @@ public: const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -119,6 +109,7 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic(); @@ -126,13 +117,25 @@ public: GetPluginName() override; uint32_t - GetPluginVersion() override + GetPluginVersion() override { return 1; } +protected: + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + bool + RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); + private: - ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_i386() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h +#endif // liblldb_ABISysV_i386_h_ diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index e1fc13a691af..3c7e9495d6ce 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_sr, - gcc_dwarf_lo, - gcc_dwarf_hi, - gcc_dwarf_bad, - gcc_dwarf_cause, - gcc_dwarf_pc -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_sr, - gdb_lo, - gdb_hi, - gdb_bad, - gdb_cause, - gdb_pc + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_sr, + dwarf_lo, + dwarf_hi, + dwarf_bad, + dwarf_cause, + dwarf_pc }; static const RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS - // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== =============== - { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_INVALID_REGNUM, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_INVALID_REGNUM, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_INVALID_REGNUM, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGINS LLDB NATIVE VALUE REGS INVALIDATE REGS + // ======== ====== == === ============= =========== ============ ============== ============ ================= =================== ========== ================= + { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -284,6 +241,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); if (log) log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); @@ -305,7 +263,14 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr)) return false; - + + if (log) + log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + + // All callers of position independent functions must place the address of the called function in t9 (r25) + if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr)) + return false; + return true; } @@ -325,8 +290,8 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -341,7 +306,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -382,7 +347,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); @@ -398,40 +363,41 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje ValueObjectSP -ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; - value.SetClangType(return_clang_type); + value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - bool is_signed; + bool is_signed = false; + bool is_complex = false; + uint32_t count = 0; // 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); - if (return_clang_type.IsIntegerType (is_signed)) + if (return_compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = return_clang_type.GetBitSize(&thread); - switch (bit_width) { default: @@ -468,11 +434,57 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla break; } } - else if (return_clang_type.IsPointerType ()) + else if (return_compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } + else if (return_compiler_type.IsAggregateType ()) + { + // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. + uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + // We have got the address. Create a memory object out of it + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (mem_address, NULL), + return_compiler_type); + return return_valobj_sp; + } + else if (return_compiler_type.IsFloatingPointType (count, is_complex)) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + + if (count == 1 && !is_complex) + { + switch (bit_width) + { + default: + return return_valobj_sp; + case 64: + { + static_assert(sizeof(double) == sizeof(uint64_t), ""); + uint64_t raw_value; + raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; + raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32; + value.GetScalar() = *reinterpret_cast(&raw_value); + break; + } + case 32: + { + static_assert(sizeof(float) == sizeof(uint32_t), ""); + uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; + value.GetScalar() = *reinterpret_cast(&raw_value); + break; + } + } + } + else + { + // not handled yet + return return_valobj_sp; + } + } else { // not handled yet @@ -496,17 +508,17 @@ ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); // Our Call Frame Address is the stack pointer value - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); // The previous PC is in the RA - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); // All other registers are the same. unwind_plan.SetSourceName ("mips at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); + unwind_plan.SetReturnAddressRegister(dwarf_r31); return true; } @@ -518,9 +530,9 @@ ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("mips default unwind plan"); @@ -542,13 +554,36 @@ ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { // Preserved registers are : // r16-r23, r28, r29, r30, r31 + const char *name = reg_info->name; - int reg = ((reg_info->byte_offset) / 4); - - bool save = (reg >= 16) && (reg <= 23); - save |= (reg >= 28) && (reg <= 31); + if (name[0] == 'r') + { + switch (name[1]) + { + case '1': + if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19 + return name[3] == '\0'; + break; + case '2': + if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3' // r20-r23 + || name[2] == '8' || name[2] == '9') // r28 and r29 + return name[3] == '\0'; + break; + case '3': + if (name[2] == '0' || name[2] == '1') // r30 and r31 + return name[3] == '\0'; + break; + } - return save; + if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28) + return true; + if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29) + return true; + if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30) + return true; + if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31) + return true; + } } return false; } diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index ad47ac222932..709c3bfe3adf 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -21,49 +21,40 @@ class ABISysV_mips : public lldb_private::ABI { public: + ~ABISysV_mips() override = default; - ~ABISysV_mips() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -73,21 +64,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc)//must- check + bool + CodeAddressIsValid(lldb::addr_t pc) override { - if (pc & (4ull - 1ull)) - return false; // Not 4 byte aligned - - // Anything else if fair game.. - return true; + // Just make sure the address is a valid 32 bit address. Bit zero + // might be set due to MicroMIPS function calls, so don't enforce alignment. + return (pc <= UINT32_MAX); } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,21 +94,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_mips() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips_h_ diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index c790fa7e7bdd..bc62c9fe82ee 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_sr, - gcc_dwarf_lo, - gcc_dwarf_hi, - gcc_dwarf_bad, - gcc_dwarf_cause, - gcc_dwarf_pc -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_sr, - gdb_lo, - gdb_hi, - gdb_bad, - gdb_cause, - gdb_pc + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_sr, + dwarf_lo, + dwarf_hi, + dwarf_bad, + dwarf_cause, + dwarf_pc }; static const RegisterInfo g_register_infos_mips64[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS - // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== =============== - { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS + // ======== ====== == === ============= ========== ============= ================= ==================== ================= ==================== ========== =============== + { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64); @@ -290,8 +247,8 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -313,7 +270,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - const uint32_t type_flags = clang_type.GetTypeInfo (NULL); + const uint32_t type_flags = compiler_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) @@ -368,42 +325,50 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP -ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - + Error error; + ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; - value.SetClangType(return_clang_type); + value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const size_t byte_size = return_clang_type.GetByteSize(nullptr); - const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); + Target *target = exe_ctx.GetTargetPtr(); + ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + + const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); + const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); - if (type_flags & eTypeIsScalar) + if (type_flags & eTypeIsScalar || + type_flags & eTypeIsPointer) { value.SetValueType(Value::eValueTypeScalar); bool success = false; - if (type_flags & eTypeIsInteger) + if (type_flags & eTypeIsInteger || + type_flags & eTypeIsPointer) { // Extract the register context so we can read arguments from registers // In MIPS register "r2" (v0) holds the integer function return values - uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -444,25 +409,302 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c break; } } + else if (type_flags & eTypeIsFloat) + { + if (type_flags & eTypeIsComplex) + { + // Don't handle complex yet. + } + else + { + if (byte_size <= sizeof(long double)) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + RegisterValue f0_value, f2_value; + DataExtractor f0_data, f2_data; + + reg_ctx->ReadRegister (f0_info, f0_value); + reg_ctx->ReadRegister (f2_info, f2_value); + + f0_value.GetData(f0_data); + f2_value.GetData(f2_data); + + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float) f0_data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double) f0_data.GetDouble(&offset); + success = true; + } + else if (byte_size == sizeof(long double)) + { + DataExtractor *copy_from_extractor = NULL; + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + if (target_byte_order == eByteOrderLittle) + { + f0_data.Append(f2_data); + copy_from_extractor = &f0_data; + } + else + { + f2_data.Append(f0_data); + copy_from_extractor = &f2_data; + } + + copy_from_extractor->CopyByteOrderedData (0, + byte_size, + data_sp->GetBytes(), + byte_size, + target_byte_order); + + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + return return_valobj_sp; + + } + } + } + } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } - else if (type_flags & eTypeIsPointer) + else if (type_flags & eTypeIsStructUnion || + type_flags & eTypeIsClass || + type_flags & eTypeIsVector) { - value.SetValueType(Value::eValueTypeScalar); - uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); - value.GetScalar() = (uint64_t)(raw_value); + // Any structure of up to 16 bytes in size is returned in the registers. + if (byte_size <= 16) + { + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value; + + uint32_t integer_bytes = 0; // Tracks how much bytes of r2 and r3 registers we've consumed so far + bool use_fp_regs = 0; // True if return values are in FP return registers. + bool found_non_fp_field = 0; // True if we found any non floating point field in structure. + bool use_r2 = 0; // True if return values are in r2 register. + bool use_r3 = 0; // True if return values are in r3 register. + bool sucess = 0; // True if the result is copied into our data buffer + std::string name; + bool is_complex; + uint32_t count; + const uint32_t num_children = return_compiler_type.GetNumFields (); + + // A structure consisting of one or two FP values (and nothing else) will be + // returned in the two FP return-value registers i.e fp0 and fp2. + if (num_children <= 2) + { + uint64_t field_bit_offset = 0; - return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), - value, - ConstString("")); - } - else if (type_flags & eTypeIsVector) - { - // TODO: Handle vector types + // Check if this structure contains only floating point fields + for (uint32_t idx = 0; idx < num_children; idx++) + { + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + + if (field_compiler_type.IsFloatingPointType (count, is_complex)) + use_fp_regs = 1; + else + found_non_fp_field = 1; + } + + if (use_fp_regs && !found_non_fp_field) + { + // We have one or two FP-only values in this structure. Get it from f0/f2 registers. + DataExtractor f0_data, f1_data, f2_data; + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + + reg_ctx->ReadRegister (f0_info, f0_value); + reg_ctx->ReadRegister (f2_info, f2_value); + + f0_value.GetData(f0_data); + f2_value.GetData(f2_data); + + for (uint32_t idx = 0; idx < num_children; idx++) + { + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); + + DataExtractor *copy_from_extractor = NULL; + + if (idx == 0) + { + if (field_byte_width == 16) // This case is for long double type. + { + // If structure contains long double type, then it is returned in fp0/fp1 registers. + reg_ctx->ReadRegister (f1_info, f1_value); + f1_value.GetData(f1_data); + + if (target_byte_order == eByteOrderLittle) + { + f0_data.Append(f1_data); + copy_from_extractor = &f0_data; + } + else + { + f1_data.Append(f0_data); + copy_from_extractor = &f1_data; + } + } + else + copy_from_extractor = &f0_data; // This is in f0, copy from register to our result structure + } + else + copy_from_extractor = &f2_data; // This is in f2, copy from register to our result structure + + // Sanity check to avoid crash + if (!copy_from_extractor || 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, + target_byte_order); + } + + // The result is in our data buffer. Create a variable object out of it + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + + return return_valobj_sp; + } + } + + // If we reach here, it means this structure either contains more than two fields or + // it contains at least one non floating point type. + // In that case, all fields are returned in GP return registers. + for (uint32_t idx = 0; idx < num_children; idx++) + { + uint64_t field_bit_offset = 0; + bool is_signed; + uint32_t padding; + + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_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) + break; + + uint32_t field_byte_offset = field_bit_offset/8; + + if (field_compiler_type.IsIntegerType (is_signed) + || field_compiler_type.IsPointerType () + || field_compiler_type.IsFloatingPointType (count, is_complex)) + { + padding = field_byte_offset - integer_bytes; + + if (integer_bytes < 8) + { + // We have not yet consumed r2 completely. + 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 + 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 + 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; + use_r3 = 1; + } + else + { + // There isn't any space left for this field, this should not happen as we have already checked + // the overall size is not greater than 16 bytes. For now, return a NULL return value object. + return return_valobj_sp; + } + } + } + // Vector types upto 16 bytes are returned in GP return registers + if (type_flags & eTypeIsVector) + { + if (byte_size <= 8) + use_r2 = 1; + else + { + use_r2 = 1; + use_r3 = 1; + } + } + + if (use_r2) + { + reg_ctx->ReadRegister (r2_info, r2_value); + + const size_t bytes_copied = r2_value.GetAsMemoryData (r2_info, + data_sp->GetBytes(), + r2_info->byte_size, + target_byte_order, + error); + if (bytes_copied != r2_info->byte_size) + return return_valobj_sp; + sucess = 1; + } + if (use_r3) + { + reg_ctx->ReadRegister (r3_info, r3_value); + const size_t bytes_copied = r3_value.GetAsMemoryData (r3_info, + data_sp->GetBytes() + r2_info->byte_size, + r3_info->byte_size, + target_byte_order, + error); + + if (bytes_copied != r3_info->byte_size) + return return_valobj_sp; + sucess = 1; + } + if (sucess) + { + // The result is in our data buffer. Create a variable object out of it + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + } + return return_valobj_sp; + } + + // Any structure/vector greater than 16 bytes in size is returned in memory. + // The pointer to that memory is returned in r2. + uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + + // We have got the address. Create a memory object out of it + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (mem_address, NULL), + return_compiler_type); } return return_valobj_sp; } @@ -476,17 +718,17 @@ ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); // Our Call Frame Address is the stack pointer value - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); // The previous PC is in the RA - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); // All other registers are the same. unwind_plan.SetSourceName ("mips64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); + unwind_plan.SetReturnAddressRegister(dwarf_r31); return true; } @@ -498,9 +740,9 @@ ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("mips64 default unwind plan"); diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index c37e717e0938..3290331e05a0 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -21,46 +21,37 @@ class ABISysV_mips64 : public lldb_private::ABI { public: + ~ABISysV_mips64() override = default; - ~ABISysV_mips64() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV mips ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -83,8 +74,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { if (pc & (4ull - 1ull)) return false; // Not 4 byte aligned @@ -93,11 +84,13 @@ public: return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -113,21 +106,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_mips64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips64_h_ diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index 08416dc25b08..f0da18637ba8 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,123 +33,81 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_f0, - gcc_dwarf_f1, - gcc_dwarf_f2, - gcc_dwarf_f3, - gcc_dwarf_f4, - gcc_dwarf_f5, - gcc_dwarf_f6, - gcc_dwarf_f7, - gcc_dwarf_f8, - gcc_dwarf_f9, - gcc_dwarf_f10, - gcc_dwarf_f11, - gcc_dwarf_f12, - gcc_dwarf_f13, - gcc_dwarf_f14, - gcc_dwarf_f15, - gcc_dwarf_f16, - gcc_dwarf_f17, - gcc_dwarf_f18, - gcc_dwarf_f19, - gcc_dwarf_f20, - gcc_dwarf_f21, - gcc_dwarf_f22, - gcc_dwarf_f23, - gcc_dwarf_f24, - gcc_dwarf_f25, - gcc_dwarf_f26, - gcc_dwarf_f27, - gcc_dwarf_f28, - gcc_dwarf_f29, - gcc_dwarf_f30, - gcc_dwarf_f31, - gcc_dwarf_cr, - gcc_dwarf_fpscr, - gcc_dwarf_xer = 101, - gcc_dwarf_lr = 108, - gcc_dwarf_ctr, - gcc_dwarf_pc, - gcc_dwarf_cfa, + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_f0, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + dwarf_f8, + dwarf_f9, + dwarf_f10, + dwarf_f11, + dwarf_f12, + dwarf_f13, + dwarf_f14, + dwarf_f15, + dwarf_f16, + dwarf_f17, + dwarf_f18, + dwarf_f19, + dwarf_f20, + dwarf_f21, + dwarf_f22, + dwarf_f23, + dwarf_f24, + dwarf_f25, + dwarf_f26, + dwarf_f27, + dwarf_f28, + dwarf_f29, + dwarf_f30, + dwarf_f31, + dwarf_cr, + dwarf_fpscr, + dwarf_xer = 101, + dwarf_lr = 108, + dwarf_ctr, + dwarf_pc, + dwarf_cfa, }; -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_lr, - gdb_cr, - gdb_xer, - gdb_ctr, - gdb_pc, -}; - - // Note that the size and offset will be updated by platform-specific classes. #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, 8, 0, eEncodingUint, \ @@ -158,45 +115,45 @@ enum gdb_regnums static const RegisterInfo g_register_infos[] = { - // General purpose registers. GCC, DWARF, Generic, GDB - DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), - DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), - DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), - DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), - DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), - DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), - DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), - DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), - DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), - DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), - DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), - DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), - DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), - DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), - DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), - DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), - DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), - DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), - DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), - DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), - DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), - DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), - DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), - DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), - DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), - DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), - DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), - DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), - DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, + // General purpose registers. eh_frame, DWARF, Generic, Process Plugin + DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +393,25 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -476,8 +433,8 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -492,7 +449,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +475,13 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; @@ -563,22 +520,22 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +545,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +594,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +638,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -709,7 +666,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } @@ -724,15 +681,15 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -740,8 +697,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -768,7 +725,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -781,8 +738,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -798,7 +755,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -831,7 +788,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -858,12 +815,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -882,12 +839,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -946,7 +903,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -965,7 +922,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -978,9 +935,9 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t lr_reg_num = gcc_dwarf_lr; - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_pc; + uint32_t lr_reg_num = dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_pc; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +962,8 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_lr; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1020,7 +977,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.SetSourceName ("ppc default unwind plan"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h index a7aad300e297..99ee755631c2 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -21,52 +21,37 @@ class ABISysV_ppc : public lldb_private::ABI { public: + ~ABISysV_ppc() override = default; - ~ABISysV_ppc() - { - } + size_t + GetRedZoneSize() const override; - virtual size_t - GetRedZoneSize () const; - - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV ppc ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -123,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_ppc() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc_h_ diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index eb0d7c00070f..96c54ce97eec 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,120 +33,79 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_f0, - gcc_dwarf_f1, - gcc_dwarf_f2, - gcc_dwarf_f3, - gcc_dwarf_f4, - gcc_dwarf_f5, - gcc_dwarf_f6, - gcc_dwarf_f7, - gcc_dwarf_f8, - gcc_dwarf_f9, - gcc_dwarf_f10, - gcc_dwarf_f11, - gcc_dwarf_f12, - gcc_dwarf_f13, - gcc_dwarf_f14, - gcc_dwarf_f15, - gcc_dwarf_f16, - gcc_dwarf_f17, - gcc_dwarf_f18, - gcc_dwarf_f19, - gcc_dwarf_f20, - gcc_dwarf_f21, - gcc_dwarf_f22, - gcc_dwarf_f23, - gcc_dwarf_f24, - gcc_dwarf_f25, - gcc_dwarf_f26, - gcc_dwarf_f27, - gcc_dwarf_f28, - gcc_dwarf_f29, - gcc_dwarf_f30, - gcc_dwarf_f31, - gcc_dwarf_cr, - gcc_dwarf_fpscr, - gcc_dwarf_xer = 101, - gcc_dwarf_lr = 108, - gcc_dwarf_ctr, - gcc_dwarf_pc, - gcc_dwarf_cfa, -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_lr, - gdb_cr, - gdb_xer, - gdb_ctr, - gdb_pc, + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_f0, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + dwarf_f8, + dwarf_f9, + dwarf_f10, + dwarf_f11, + dwarf_f12, + dwarf_f13, + dwarf_f14, + dwarf_f15, + dwarf_f16, + dwarf_f17, + dwarf_f18, + dwarf_f19, + dwarf_f20, + dwarf_f21, + dwarf_f22, + dwarf_f23, + dwarf_f24, + dwarf_f25, + dwarf_f26, + dwarf_f27, + dwarf_f28, + dwarf_f29, + dwarf_f30, + dwarf_f31, + dwarf_cr, + dwarf_fpscr, + dwarf_xer = 101, + dwarf_lr = 108, + dwarf_ctr, + dwarf_pc, + dwarf_cfa, }; @@ -158,45 +116,45 @@ enum gdb_regnums static const RegisterInfo g_register_infos[] = { - // General purpose registers. GCC, DWARF, Generic, GDB - DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), - DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), - DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), - DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), - DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), - DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), - DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), - DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), - DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), - DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), - DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), - DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), - DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), - DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), - DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), - DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), - DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), - DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), - DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), - DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), - DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), - DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), - DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), - DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), - DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), - DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), - DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), - DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), - DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, + // General purpose registers. eh_frame, DWARF, Generic, Process Plugin + DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +394,25 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -476,8 +434,8 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -492,7 +450,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +476,13 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; @@ -563,22 +521,22 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +546,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +595,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +639,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -709,7 +667,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } @@ -724,15 +682,15 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -740,8 +698,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -768,7 +726,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -781,8 +739,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -798,7 +756,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -831,7 +789,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -858,12 +816,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -882,12 +840,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -946,7 +904,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -965,7 +923,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -978,9 +936,9 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t lr_reg_num = gcc_dwarf_lr; - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_pc; + uint32_t lr_reg_num = dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_pc; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +963,8 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_lr; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1015,13 +973,13 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); - row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true); + row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("ppc64 default unwind plan"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h index d77cb9f1efe3..b87f7938d544 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -21,52 +21,37 @@ class ABISysV_ppc64 : public lldb_private::ABI { public: + ~ABISysV_ppc64() override = default; - ~ABISysV_ppc64() - { - } + size_t + GetRedZoneSize() const override; - virtual size_t - GetRedZoneSize () const; - - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV ppc64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -123,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_ppc64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc64_h_ diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 1d63628466c2..11e383d269c3 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,222 +33,144 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_rax = 0, - gcc_dwarf_rdx, - gcc_dwarf_rcx, - gcc_dwarf_rbx, - gcc_dwarf_rsi, - gcc_dwarf_rdi, - gcc_dwarf_rbp, - gcc_dwarf_rsp, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_rip, - gcc_dwarf_xmm0, - gcc_dwarf_xmm1, - gcc_dwarf_xmm2, - gcc_dwarf_xmm3, - gcc_dwarf_xmm4, - gcc_dwarf_xmm5, - gcc_dwarf_xmm6, - gcc_dwarf_xmm7, - gcc_dwarf_xmm8, - gcc_dwarf_xmm9, - gcc_dwarf_xmm10, - gcc_dwarf_xmm11, - gcc_dwarf_xmm12, - gcc_dwarf_xmm13, - gcc_dwarf_xmm14, - gcc_dwarf_xmm15, - gcc_dwarf_stmm0, - gcc_dwarf_stmm1, - gcc_dwarf_stmm2, - gcc_dwarf_stmm3, - gcc_dwarf_stmm4, - gcc_dwarf_stmm5, - gcc_dwarf_stmm6, - gcc_dwarf_stmm7, - gcc_dwarf_ymm0, - gcc_dwarf_ymm1, - gcc_dwarf_ymm2, - gcc_dwarf_ymm3, - gcc_dwarf_ymm4, - gcc_dwarf_ymm5, - gcc_dwarf_ymm6, - gcc_dwarf_ymm7, - gcc_dwarf_ymm8, - gcc_dwarf_ymm9, - gcc_dwarf_ymm10, - gcc_dwarf_ymm11, - gcc_dwarf_ymm12, - gcc_dwarf_ymm13, - gcc_dwarf_ymm14, - gcc_dwarf_ymm15 + dwarf_rax = 0, + dwarf_rdx, + dwarf_rcx, + dwarf_rbx, + dwarf_rsi, + dwarf_rdi, + dwarf_rbp, + dwarf_rsp, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_rip, + dwarf_xmm0, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7, + dwarf_xmm8, + dwarf_xmm9, + dwarf_xmm10, + dwarf_xmm11, + dwarf_xmm12, + dwarf_xmm13, + dwarf_xmm14, + dwarf_xmm15, + dwarf_stmm0, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_ymm0, + dwarf_ymm1, + dwarf_ymm2, + dwarf_ymm3, + dwarf_ymm4, + dwarf_ymm5, + dwarf_ymm6, + dwarf_ymm7, + dwarf_ymm8, + dwarf_ymm9, + dwarf_ymm10, + dwarf_ymm11, + dwarf_ymm12, + dwarf_ymm13, + dwarf_ymm14, + dwarf_ymm15 }; -enum gdb_regnums -{ - gdb_rax = 0, - gdb_rbx = 1, - gdb_rcx = 2, - gdb_rdx = 3, - gdb_rsi = 4, - gdb_rdi = 5, - gdb_rbp = 6, - gdb_rsp = 7, - gdb_r8 = 8, - gdb_r9 = 9, - gdb_r10 = 10, - gdb_r11 = 11, - gdb_r12 = 12, - gdb_r13 = 13, - gdb_r14 = 14, - gdb_r15 = 15, - gdb_rip = 16, - gdb_rflags = 17, - gdb_cs = 18, - gdb_ss = 19, - gdb_ds = 20, - gdb_es = 21, - gdb_fs = 22, - gdb_gs = 23, - gdb_stmm0 = 24, - gdb_stmm1 = 25, - gdb_stmm2 = 26, - gdb_stmm3 = 27, - gdb_stmm4 = 28, - gdb_stmm5 = 29, - gdb_stmm6 = 30, - gdb_stmm7 = 31, - gdb_fctrl = 32, gdb_fcw = gdb_fctrl, - gdb_fstat = 33, gdb_fsw = gdb_fstat, - gdb_ftag = 34, gdb_ftw = gdb_ftag, - gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 36, gdb_ip = gdb_fioff, - gdb_foseg = 37, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 38, gdb_dp = gdb_fooff, - gdb_fop = 39, - gdb_xmm0 = 40, - gdb_xmm1 = 41, - gdb_xmm2 = 42, - gdb_xmm3 = 43, - gdb_xmm4 = 44, - gdb_xmm5 = 45, - gdb_xmm6 = 46, - gdb_xmm7 = 47, - gdb_xmm8 = 48, - gdb_xmm9 = 49, - gdb_xmm10 = 50, - gdb_xmm11 = 51, - gdb_xmm12 = 52, - gdb_xmm13 = 53, - gdb_xmm14 = 54, - gdb_xmm15 = 55, - gdb_mxcsr = 56, - gdb_ymm0 = 57, - gdb_ymm1 = 58, - gdb_ymm2 = 59, - gdb_ymm3 = 60, - gdb_ymm4 = 61, - gdb_ymm5 = 62, - gdb_ymm6 = 63, - gdb_ymm7 = 64, - gdb_ymm8 = 65, - gdb_ymm9 = 66, - gdb_ymm10 = 67, - gdb_ymm11 = 68, - gdb_ymm12 = 69, - gdb_ymm13 = 70, - gdb_ymm14 = 71, - gdb_ymm15 = 72 -}; - - static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ======== ======= == === ============= =================== ======================= ===================== =========================== ===================== ====================== ========== =============== - { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rax , gcc_dwarf_rax , LLDB_INVALID_REGNUM , gdb_rax , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbx , gcc_dwarf_rbx , LLDB_INVALID_REGNUM , gdb_rbx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rcx , gcc_dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , gdb_rcx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdx , gcc_dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , gdb_rdx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsi , gcc_dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , gdb_rsi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdi , gcc_dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , gdb_rdi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbp , gcc_dwarf_rbp , LLDB_REGNUM_GENERIC_FP , gdb_rbp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsp , gcc_dwarf_rsp , LLDB_REGNUM_GENERIC_SP , gdb_rsp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r8 , gcc_dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , gdb_r8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r9 , gcc_dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , gdb_r9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r10 , gcc_dwarf_r10 , LLDB_INVALID_REGNUM , gdb_r10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r11 , gcc_dwarf_r11 , LLDB_INVALID_REGNUM , gdb_r11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r12 , gcc_dwarf_r12 , LLDB_INVALID_REGNUM , gdb_r12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r13 , gcc_dwarf_r13 , LLDB_INVALID_REGNUM , gdb_r13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r14 , gcc_dwarf_r14 , LLDB_INVALID_REGNUM , gdb_r14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r15 , gcc_dwarf_r15 , LLDB_INVALID_REGNUM , gdb_r15 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rip , gcc_dwarf_rip , LLDB_REGNUM_GENERIC_PC , gdb_rip , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0 , gcc_dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1 , gcc_dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2 , gcc_dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3 , gcc_dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4 , gcc_dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5 , gcc_dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6 , gcc_dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7 , gcc_dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , LLDB_INVALID_REGNUM , gdb_xmm8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , LLDB_INVALID_REGNUM , gdb_xmm9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10 , gcc_dwarf_xmm10 , LLDB_INVALID_REGNUM , gdb_xmm10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11 , gcc_dwarf_xmm11 , LLDB_INVALID_REGNUM , gdb_xmm11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12 , gcc_dwarf_xmm12 , LLDB_INVALID_REGNUM , gdb_xmm12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13 , gcc_dwarf_xmm13 , LLDB_INVALID_REGNUM , gdb_xmm13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14 , gcc_dwarf_xmm14 , LLDB_INVALID_REGNUM , gdb_xmm14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15 , gcc_dwarf_xmm15 , LLDB_INVALID_REGNUM , gdb_xmm15 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , LLDB_INVALID_REGNUM , gdb_ymm8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , LLDB_INVALID_REGNUM , gdb_ymm9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10 , gcc_dwarf_ymm10 , LLDB_INVALID_REGNUM , gdb_ymm10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11 , gcc_dwarf_ymm11 , LLDB_INVALID_REGNUM , gdb_ymm11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12 , gcc_dwarf_ymm12 , LLDB_INVALID_REGNUM , gdb_ymm12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13 , gcc_dwarf_ymm13 , LLDB_INVALID_REGNUM , gdb_ymm13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14 , gcc_dwarf_ymm14 , LLDB_INVALID_REGNUM , gdb_ymm14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15 , gcc_dwarf_ymm15 , LLDB_INVALID_REGNUM , gdb_ymm15 , LLDB_INVALID_REGNUM }, NULL, NULL} + { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rax , dwarf_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rbx , dwarf_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { dwarf_rcx , dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdx , dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsi , dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdi , dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rbp , dwarf_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsp , dwarf_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { dwarf_r8 , dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { dwarf_r9 , dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r10 , dwarf_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r11 , dwarf_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r12 , dwarf_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r13 , dwarf_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r14 , dwarf_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r15 , dwarf_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { dwarf_rip , dwarf_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm0 , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm1 , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm2 , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm3 , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm4 , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm5 , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm6 , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm7 , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm0 , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm1 , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm2 , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm3 , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm4 , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm5 , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm6 , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm7 , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm8 , dwarf_xmm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm9 , dwarf_xmm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm10 , dwarf_xmm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm11 , dwarf_xmm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm12 , dwarf_xmm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm13 , dwarf_xmm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm14 , dwarf_xmm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm15 , dwarf_xmm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm0 , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm1 , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm2 , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm3 , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm4 , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm5 , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm6 , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm7 , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm8 , dwarf_ymm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm9 , dwarf_ymm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm10 , dwarf_ymm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm11 , dwarf_ymm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm12 , dwarf_ymm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm13 , dwarf_ymm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm14 , dwarf_ymm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm15 , dwarf_ymm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -502,25 +423,25 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -542,8 +463,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -558,7 +479,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0); @@ -584,13 +505,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -633,22 +554,22 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -658,7 +579,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -707,7 +628,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -755,18 +676,13 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); + if (altivec_reg == nullptr) + altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); - if (altivec_reg == NULL) - { - altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - } - if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -790,13 +706,52 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } } } } + 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 heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + RegisterValue reg_value2; + if (reg_ctx->ReadRegister(altivec_reg, reg_value) && reg_ctx->ReadRegister(altivec_reg2, reg_value2)) + { + + Error error; + if (reg_value.GetAsMemoryData (altivec_reg, + heap_data_ap->GetBytes(), + altivec_reg->byte_size, + byte_order, + error) && + reg_value2.GetAsMemoryData (altivec_reg2, + heap_data_ap->GetBytes() + altivec_reg->byte_size, + heap_data_ap->GetByteSize() - altivec_reg->byte_size, + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + data); + } + } + } + } + } } } } @@ -805,15 +760,15 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -821,8 +776,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -855,7 +810,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -868,8 +823,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_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) @@ -889,7 +844,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -922,7 +877,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -955,12 +910,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -979,12 +934,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -1048,7 +1003,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -1067,7 +1022,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -1084,8 +1039,8 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_rsp; - uint32_t pc_reg_num = gcc_dwarf_rip; + uint32_t sp_reg_num = dwarf_rsp; + uint32_t pc_reg_num = dwarf_rip; UnwindPlan::RowSP row(new UnwindPlan::Row); row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8); @@ -1108,14 +1063,14 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t fp_reg_num = gcc_dwarf_rbp; - uint32_t sp_reg_num = gcc_dwarf_rsp; - uint32_t pc_reg_num = gcc_dwarf_rip; + uint32_t fp_reg_num = dwarf_rbp; + uint32_t sp_reg_num = dwarf_rsp; + uint32_t pc_reg_num = dwarf_rip; UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 8; - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset (0); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); 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 6fefcc2a9c74..07b57abaf57c 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -21,46 +21,37 @@ class ABISysV_x86_64 : public lldb_private::ABI { public: + ~ABISysV_x86_64() override = default; - ~ABISysV_x86_64() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV x86_64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -83,19 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -111,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_x86_64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_x86_64_h_ diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index d20219f6d1eb..6d124b689341 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "DisassemblerLLVMC.h" - +// C Includes +// C++ Includes +// Project includes #include "llvm-c/Disassembler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -25,6 +26,8 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" +// Other libraries and framework includes +#include "DisassemblerLLVMC.h" #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" @@ -52,18 +55,16 @@ public: Instruction (address, addr_class), m_disasm_sp (disasm.shared_from_this()), m_does_branch (eLazyBoolCalculate), + m_has_delay_slot (eLazyBoolCalculate), m_is_valid (false), m_using_file_addr (false) { } - virtual - ~InstructionLLVMC () - { - } + ~InstructionLLVMC() override = default; - virtual bool - DoesBranch () + bool + DoesBranch() override { if (m_does_branch == eLazyBoolCalculate) { @@ -99,6 +100,43 @@ public: return m_does_branch == eLazyBoolYes; } + bool + HasDelaySlot() override + { + if (m_has_delay_slot == eLazyBoolCalculate) + { + GetDisassemblerLLVMC().Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) + { + bool is_alternate_isa; + lldb::addr_t pc = m_address.GetFileAddress(); + + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); + // if we didn't understand the instruction, say it doesn't have a delay slot... + if (inst_size == 0) + m_has_delay_slot = eLazyBoolNo; + else + { + const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); + if (has_delay_slot) + m_has_delay_slot = eLazyBoolYes; + else + m_has_delay_slot = eLazyBoolNo; + } + } + GetDisassemblerLLVMC().Unlock(); + } + return m_has_delay_slot == eLazyBoolYes; + } + DisassemblerLLVMC::LLVMCDisassembler * GetDisasmToUse (bool &is_alternate_isa) { @@ -117,10 +155,10 @@ public: return llvm_disasm.m_disasm_ap.get(); } - virtual size_t - Decode (const lldb_private::Disassembler &disassembler, - const lldb_private::DataExtractor &data, - lldb::offset_t data_offset) + size_t + Decode(const lldb_private::Disassembler &disassembler, + const lldb_private::DataExtractor &data, + lldb::offset_t data_offset) override { // All we have to do is read the opcode which can be easy for some // architectures @@ -234,15 +272,16 @@ public: } } - virtual void - CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) + void + CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data)) { - char out_string[512]; + std::string out_string; + std::string comment_string; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); @@ -293,7 +332,12 @@ public: if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); - mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); + mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); + + if (!comment_string.empty()) + { + AppendComment(comment_string); + } } llvm_disasm.Unlock(); @@ -375,10 +419,10 @@ public: RegularExpression::Match matches(3); - if (s_regex.Execute(out_string, &matches)) + if (s_regex.Execute(out_string.c_str(), &matches)) { - matches.GetMatchAtIndex(out_string, 1, m_opcode_name); - matches.GetMatchAtIndex(out_string, 2, m_mnemonics); + matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); + matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); } } } @@ -409,12 +453,11 @@ protected: DisassemblerSP m_disasm_sp; // for ownership LazyBool m_does_branch; + LazyBool m_has_delay_slot; bool m_is_valid; bool m_using_file_addr; }; - - DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner): m_is_valid(true) { @@ -482,9 +525,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con m_is_valid = false; } -DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() -{ -} +DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default; uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, @@ -508,22 +549,25 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, return 0; } -uint64_t +void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, - char *dst, - size_t dst_len) + std::string &inst_string, + std::string &comments_string) { - llvm::StringRef unused_annotations; - llvm::SmallString<64> inst_string; - llvm::raw_svector_ostream inst_stream(inst_string); - m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations, - *m_subtarget_info_ap); - inst_stream.flush(); - const size_t output_size = std::min(dst_len - 1, inst_string.size()); - std::memcpy(dst, inst_string.data(), output_size); - dst[output_size] = '\0'; - - return output_size; + llvm::raw_string_ostream inst_stream(inst_string); + llvm::raw_string_ostream comments_stream(comments_string); + + m_instr_printer_ap->setCommentStream(comments_stream); + m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap); + m_instr_printer_ap->setCommentStream(llvm::nulls()); + comments_stream.flush(); + + static std::string g_newlines("\r\n"); + + for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/) + { + comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' '); + } } void @@ -544,35 +588,9 @@ DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst) } bool -DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst) { - llvm::Triple triple = arch.GetTriple(); - if (flavor == NULL || strcmp (flavor, "default") == 0) - return true; - - if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) - { - if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) - return true; - else - return false; - } - else - return false; -} - - -Disassembler * -DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) -{ - if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) - { - std::unique_ptr disasm_ap (new DisassemblerLLVMC(arch, flavor)); - - if (disasm_ap.get() && disasm_ap->IsValid()) - return disasm_ap.release(); - } - return NULL; + return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot(); } DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) : @@ -586,13 +604,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_flavor.assign("default"); } - const char *triple = arch.GetTriple().getTriple().c_str(); unsigned flavor = ~0U; + llvm::Triple triple = arch.GetTriple(); // So far the only supported flavor is "intel" on x86. The base class will set this // correctly coming in. - if (arch.GetTriple().getArch() == llvm::Triple::x86 - || arch.GetTriple().getArch() == llvm::Triple::x86_64) + if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) { if (m_flavor == "intel") { @@ -605,7 +622,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } ArchSpec thumb_arch(arch); - if (arch.GetTriple().getArch() == llvm::Triple::arm) + if (triple.getArch() == llvm::Triple::arm) { std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str()); // Replace "arm" with "thumb" so we get all thumb variants correct @@ -621,18 +638,29 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str())); } + // If no sub architecture specified then use the most recent arm architecture so the + // disassembler will return all instruction. Without it we will see a lot of unknow opcode + // in case the code uses instructions which are not available in the oldest arm version + // (used when no sub architecture is specified) + if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch) + triple.setArchName("armv8.1a"); + + const char *triple_str = triple.getTriple().c_str(); + + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em). // // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32 // instructions defined in ARMv7-A. - if (arch.GetTriple().getArch() == llvm::Triple::arm + if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb) && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) { - triple = thumb_arch.GetTriple().getTriple().c_str(); + triple_str = thumb_arch.GetTriple().getTriple().c_str(); } const char *cpu = ""; @@ -674,8 +702,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } std::string features_str = ""; - if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel - || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) + if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel + || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el) { uint32_t arch_flags = arch.GetFlags (); if (arch_flags & ArchSpec::eMIPSAse_msa) @@ -684,13 +712,9 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s features_str += "+dsp,"; if (arch_flags & ArchSpec::eMIPSAse_dspr2) features_str += "+dspr2,"; - if (arch_flags & ArchSpec::eMIPSAse_mips16) - features_str += "+mips16,"; - if (arch_flags & ArchSpec::eMIPSAse_micromips) - features_str += "+micromips,"; } - m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this)); + m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this)); if (!m_disasm_ap->IsValid()) { // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, @@ -698,8 +722,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_disasm_ap.reset(); } + llvm::Triple::ArchType llvm_arch = triple.getArch(); + // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler. - if (arch.GetTriple().getArch() == llvm::Triple::arm) + if (llvm_arch == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); @@ -709,10 +735,40 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_alternate_disasm_ap.reset(); } } + else if (llvm_arch == llvm::Triple::mips + || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 + || llvm_arch == llvm::Triple::mips64el) + { + /* Create alternate disassembler for MIPS16 and microMIPS */ + uint32_t arch_flags = arch.GetFlags (); + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features_str += "+mips16,"; + else if (arch_flags & ArchSpec::eMIPSAse_micromips) + features_str += "+micromips,"; + + m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this)); + if (!m_alternate_disasm_ap->IsValid()) + { + m_disasm_ap.reset(); + m_alternate_disasm_ap.reset(); + } + } } -DisassemblerLLVMC::~DisassemblerLLVMC() +DisassemblerLLVMC::~DisassemblerLLVMC() = default; + +Disassembler * +DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) { + if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) + { + std::unique_ptr disasm_ap (new DisassemblerLLVMC(arch, flavor)); + + if (disasm_ap.get() && disasm_ap->IsValid()) + return disasm_ap.release(); + } + return NULL; } size_t @@ -817,6 +873,24 @@ const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler, name); } +bool +DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +{ + llvm::Triple triple = arch.GetTriple(); + if (flavor == NULL || strcmp (flavor, "default") == 0) + return true; + + if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) + { + if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) + return true; + else + return false; + } + else + return false; +} + int DisassemblerLLVMC::OpInfo (uint64_t PC, uint64_t Offset, uint64_t Size, diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index 56cec03994ef..6359146d81d8 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -10,10 +10,20 @@ #ifndef liblldb_DisassemblerLLVMC_h_ #define liblldb_DisassemblerLLVMC_h_ +// C Includes +// C++ Includes +#include #include +// Other libraries and framework includes #include "llvm-c/Disassembler.h" +// Project includes +#include "lldb/Core/Address.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/Mutex.h" + // Opaque references to C++ Objects in LLVM's MC. namespace llvm { @@ -25,12 +35,7 @@ namespace llvm class MCInstPrinter; class MCAsmInfo; class MCSubtargetInfo; -} - -#include "lldb/Core/Address.h" -#include "lldb/Core/Disassembler.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Mutex.h" +} // namespace llvm class InstructionLLVMC; @@ -46,9 +51,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler ~LLVMCDisassembler(); uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst); - uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len); + void PrintMCInst (llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string); void SetStyle (bool use_hex_immed, HexImmediateStyle hex_style); bool CanBranch (llvm::MCInst &mc_inst); + bool HasDelaySlot (llvm::MCInst &mc_inst); bool IsValid() { return m_is_valid; @@ -66,6 +72,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler }; public: + DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); + + ~DisassemblerLLVMC() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -81,33 +91,28 @@ public: static lldb_private::Disassembler * CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor); - DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); - - virtual - ~DisassemblerLLVMC(); - - virtual size_t - DecodeInstructions (const lldb_private::Address &base_addr, - const lldb_private::DataExtractor& data, - lldb::offset_t data_offset, - size_t num_instructions, - bool append, - bool data_from_file); + size_t + DecodeInstructions(const lldb_private::Address &base_addr, + const lldb_private::DataExtractor& data, + lldb::offset_t data_offset, + size_t num_instructions, + bool append, + bool data_from_file) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: friend class InstructionLLVMC; - virtual bool - FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor); + bool + FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override; bool IsValid() @@ -163,4 +168,4 @@ protected: std::unique_ptr m_alternate_disasm_ap; }; -#endif // liblldb_DisassemblerLLVM_h_ +#endif // liblldb_DisassemblerLLVM_h_ diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 2308129b8cab..28493170ac36 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -104,11 +104,6 @@ DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic() "loads/unloads in Hexagon processes."; } -void -DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - uint32_t DynamicLoaderHexagonDYLD::GetPluginVersion() { @@ -177,7 +172,7 @@ DynamicLoaderHexagonDYLD::DidAttach() // Map the loaded sections of this executable if ( load_offset != LLDB_INVALID_ADDRESS ) - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); // AD: confirm this? // Load into LLDB all of the currently loaded executables in the stub @@ -248,18 +243,6 @@ DynamicLoaderHexagonDYLD::GetTargetExecutable() return executable; } -Error -DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - //AD: Needs to be updated? Error DynamicLoaderHexagonDYLD::CanLoadImage() @@ -268,7 +251,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage() } void -DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { Target &target = m_process->GetTarget(); const SectionList *sections = GetSectionListFromModule(module); @@ -442,7 +428,7 @@ DynamicLoaderHexagonDYLD::RefreshModules() for (I = m_rendezvous.loaded_begin(); I != E; ++I) { FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true); if (module_sp.get()) { loaded_modules.AppendIfNeeded( module_sp ); @@ -571,7 +557,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { const char *module_path = I->path.c_str(); FileSpec file(module_path, false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true); if (module_sp.get()) { module_list.Append(module_sp); @@ -591,7 +577,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules() /// Helper for the entry breakpoint callback. Resolves the load addresses /// of all dependent modules. ModuleSP -DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { Target &target = m_process->GetTarget(); ModuleList &modules = target.GetImages(); @@ -602,12 +591,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_ // check if module is currently loaded if ((module_sp = modules.FindFirstModule (module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, true); } // try to load this module from disk else if ((module_sp = target.GetSharedModule(module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, true); } return module_sp; diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h index aafa385c0fca..e10d4ee64209 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderHexagon_H_ -#define liblldb_DynamicLoaderHexagon_H_ +#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" @@ -21,6 +22,9 @@ class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader { public: + DynamicLoaderHexagonDYLD(lldb_private::Process *process); + + ~DynamicLoaderHexagonDYLD() override; static void Initialize(); @@ -37,48 +41,34 @@ public: static lldb_private::DynamicLoader * CreateInstance(lldb_private::Process *process, bool force); - DynamicLoaderHexagonDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderHexagonDYLD(); - //------------------------------------------------------------------ // DynamicLoader protocol //------------------------------------------------------------------ - virtual void - DidAttach(); + void + DidAttach() override; - virtual void - DidLaunch(); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage(); + lldb_private::Error + CanLoadImage() override; - virtual lldb::addr_t - GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); + lldb::addr_t + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + uint32_t + GetPluginVersion() override; protected: /// Runtime linker rendezvous structure. @@ -124,18 +114,22 @@ protected: void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Removes the loaded sections from the target in @p module. /// /// @param module The module to traverse. void - UnloadSections(const lldb::ModuleSP module); + UnloadSections(const lldb::ModuleSP module) override; /// Locates or creates a module given by @p file and updates/loads the /// resulting module at the virtual base address @p base_addr. lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); + LoadModuleAtAddress(const lldb_private::FileSpec &file, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Callback routine invoked when we hit the breakpoint on process entry. /// @@ -173,10 +167,10 @@ protected: FindRendezvousBreakpointAddress( ); private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD); - const lldb_private::SectionList * GetSectionListFromModule(const lldb::ModuleSP module) const; + + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD); }; -#endif // liblldb_DynamicLoaderHexagonDYLD_H_ +#endif // liblldb_DynamicLoaderHexagonDYLD_h_ diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 8b1dd283394b..09e874a011df 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -290,19 +291,13 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) // FreeBSD and on Android it is the full path to the executable. auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); - auto os_type = triple.getOS(); - auto env_type = triple.getEnvironment(); - - switch (os_type) { + switch (triple.getOS()) { case llvm::Triple::FreeBSD: return entry.file_spec == m_exe_file_spec; case llvm::Triple::Linux: - switch (env_type) { - case llvm::Triple::Android: - return entry.file_spec == m_exe_file_spec; - default: - return !entry.file_spec; - } + if (triple.isAndroid()) + return entry.file_spec == m_exe_file_spec; + return !entry.file_spec; default: return false; } @@ -372,6 +367,25 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr) return str; } +// Returns true if the load bias reported by the linker is incorrect for the given entry. This +// function is used to handle cases where we want to work around a bug in the system linker. +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. + uint32_t os_major = 0, os_minor = 0, os_update = 0; + if (target.GetArchitecture().GetTriple().isAndroid() && + target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && + (os_major == 21 || os_major == 22) && + (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) + { + return true; + } + + return false; +} + bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { @@ -413,11 +427,9 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) std::string file_path = ReadStringFromMemory(entry.path_addr); entry.file_spec.SetFile(file_path, false); - // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in - // correctly. To get the correct load address we fetch the load address of the file from the - // proc file system. - if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 && - (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) + // If the load bias reported by the linker is incorrect then fetch the load address of the file + // from the proc file system. + if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) { lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; bool is_loaded = false; diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 8724fc039cb9..6ba7b470d743 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -62,11 +62,6 @@ DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() "loads/unloads in POSIX processes."; } -void -DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - uint32_t DynamicLoaderPOSIXDYLD::GetPluginVersion() { @@ -96,7 +91,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS), m_auxv(), - m_dyld_bid(LLDB_INVALID_BREAK_ID) + m_dyld_bid(LLDB_INVALID_BREAK_ID), + m_vdso_base(LLDB_INVALID_ADDRESS) { } @@ -131,6 +127,8 @@ DynamicLoaderPOSIXDYLD::DidAttach() if (log) log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "", load_offset); + EvalVdsoStatus(); + // if we dont have a load address we cant re-base bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; @@ -165,7 +163,7 @@ DynamicLoaderPOSIXDYLD::DidAttach() m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp->GetFileSpec().GetPath().c_str ()); - UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); // When attaching to a target, there are two possible states: // (1) We already crossed the entry point and therefore the rendezvous @@ -218,12 +216,13 @@ DynamicLoaderPOSIXDYLD::DidLaunch() executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); + EvalVdsoStatus(); if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) { ModuleList module_list; module_list.Append(executable); - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); if (log) log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); @@ -233,18 +232,6 @@ DynamicLoaderPOSIXDYLD::DidLaunch() } } -Error -DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - Error DynamicLoaderPOSIXDYLD::CanLoadImage() { @@ -252,11 +239,13 @@ DynamicLoaderPOSIXDYLD::CanLoadImage() } void -DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { m_loaded_modules[module] = link_map_addr; - - UpdateLoadedSectionsCommon(module, base_addr); + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } void @@ -414,7 +403,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules() E = m_rendezvous.loaded_end(); for (I = m_rendezvous.loaded_begin(); I != E; ++I) { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { loaded_modules.AppendIfNeeded(module_sp); @@ -432,8 +421,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules() for (I = m_rendezvous.unloaded_begin(); I != E; ++I) { ModuleSpec module_spec{I->file_spec}; - ModuleSP module_sp = - loaded_modules.FindFirstModule (module_spec); + ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec); if (module_sp.get()) { @@ -519,11 +507,18 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() // that ourselves here. ModuleSP executable = GetTargetExecutable(); m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - - + if (m_vdso_base != LLDB_INVALID_ADDRESS) + { + FileSpec file_spec("[vdso]", false); + ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false); + if (module_sp.get()) + { + module_list.Append(module_sp); + } + } for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { module_list.Append(module_sp); @@ -568,6 +563,16 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset() return m_load_offset; } +void +DynamicLoaderPOSIXDYLD::EvalVdsoStatus() +{ + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + + if (I != m_auxv->end()) + m_vdso_base = I->value; + +} + addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 68d3059cb4be..cb97bbf43ba9 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// +//===-- DynamicLoaderPOSIXDYLD.h --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderPOSIX_H_ -#define liblldb_DynamicLoaderPOSIX_H_ +#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_ +#define liblldb_DynamicLoaderPOSIXDYLD_h_ // C Includes // C++ Includes // Other libraries and framework includes +// Project includes #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Target/DynamicLoader.h" @@ -23,6 +24,9 @@ class AuxVector; class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { public: + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + + ~DynamicLoaderPOSIXDYLD() override; static void Initialize(); @@ -39,48 +43,34 @@ public: static lldb_private::DynamicLoader * CreateInstance(lldb_private::Process *process, bool force); - DynamicLoaderPOSIXDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderPOSIXDYLD(); - //------------------------------------------------------------------ // DynamicLoader protocol //------------------------------------------------------------------ - virtual void - DidAttach(); + void + DidAttach() override; - virtual void - DidLaunch(); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage(); + lldb_private::Error + CanLoadImage() override; - virtual lldb::addr_t - GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); + lldb::addr_t + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + lldb_private::ConstString + GetPluginName() override; - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + uint32_t + GetPluginVersion() override; protected: /// Runtime linker rendezvous structure. @@ -98,12 +88,16 @@ protected: /// Rendezvous breakpoint. lldb::break_id_t m_dyld_bid; + /// Contains AT_SYSINFO_EHDR, which means a vDSO has been + /// mapped to the address space + lldb::addr_t m_vdso_base; + /// Loaded module list. (link map for each module) std::map> m_loaded_modules; /// Enables a breakpoint on a function called by the runtime /// linker each time a module is loaded or unloaded. - void + virtual void SetRendezvousBreakpoint(); /// Callback routine which updates the current list of loaded modules based @@ -126,16 +120,17 @@ protected: /// @param link_map_addr The virtual address of the link map for the @p module. /// /// @param base_addr The virtual base address @p module is loaded at. - virtual void + void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Removes the loaded sections from the target in @p module. /// /// @param module The module to traverse. - virtual void - UnloadSections(const lldb::ModuleSP module); + void + UnloadSections(const lldb::ModuleSP module) override; /// Resolves the entry point for the current inferior process and sets a /// breakpoint at that address. @@ -155,7 +150,7 @@ protected: /// Helper for the entry breakpoint callback. Resolves the load addresses /// of all dependent modules. - void + virtual void LoadAllCurrentModules(); /// Computes a value for m_load_offset returning the computed address on @@ -168,6 +163,11 @@ protected: lldb::addr_t GetEntryPoint(); + /// Evaluate if Aux vectors contain vDSO information + /// in case they do, read and assign the address to m_vdso_base + void + EvalVdsoStatus(); + /// Loads Module from inferior process. void ResolveExecutableModule(lldb::ModuleSP &module_sp); @@ -176,4 +176,4 @@ private: DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); }; -#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ +#endif // liblldb_DynamicLoaderPOSIXDYLD_h_ diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h index ea33164cf823..a7fdf4d22165 100644 --- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h +++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h @@ -12,12 +12,8 @@ // C Includes // C++ Includes -#include -#include -#include - // Other libraries and framework includes - +// Project includes #include "lldb/Target/DynamicLoader.h" #include "lldb/Host/FileSpec.h" #include "lldb/Core/UUID.h" @@ -27,6 +23,10 @@ class DynamicLoaderStatic : public lldb_private::DynamicLoader { public: + DynamicLoaderStatic(lldb_private::Process *process); + + ~DynamicLoaderStatic() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -45,37 +45,33 @@ public: static lldb_private::DynamicLoader * CreateInstance (lldb_private::Process *process, bool force); - DynamicLoaderStatic (lldb_private::Process *process); - - virtual - ~DynamicLoaderStatic (); //------------------------------------------------------------------ /// Called after attaching a process. /// /// Allow DynamicLoader plug-ins to execute some code after /// attaching to a process. //------------------------------------------------------------------ - virtual void - DidAttach (); + void + DidAttach() override; - virtual void - DidLaunch (); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan (lldb_private::Thread &thread, - bool stop_others); + lldb::ThreadPlanSP + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage (); + lldb_private::Error + CanLoadImage() override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; private: void @@ -84,4 +80,4 @@ private: DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic); }; -#endif // liblldb_DynamicLoaderStatic_h_ +#endif // liblldb_DynamicLoaderStatic_h_ diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index 56b56ab3a194..dd391b4ca4d2 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -21,40 +21,39 @@ using namespace lldb_private; DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process) : DynamicLoader(process) { - } DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() { - } -void DynamicLoaderWindowsDYLD::Initialize() +void +DynamicLoaderWindowsDYLD::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); + PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); } -void DynamicLoaderWindowsDYLD::Terminate() +void +DynamicLoaderWindowsDYLD::Terminate() { - } -ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() +ConstString +DynamicLoaderWindowsDYLD::GetPluginNameStatic() { static ConstString g_plugin_name("windows-dyld"); return g_plugin_name; } -const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() +const char * +DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() { return "Dynamic loader plug-in that watches for shared library " "loads/unloads in Windows processes."; } - -DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force) +DynamicLoader * +DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force) { bool should_create = force; if (!should_create) @@ -65,32 +64,35 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool f } if (should_create) - return new DynamicLoaderWindowsDYLD (process); + return new DynamicLoaderWindowsDYLD(process); return nullptr; } -void DynamicLoaderWindowsDYLD::DidAttach() +void +DynamicLoaderWindowsDYLD::DidAttach() { - } -void DynamicLoaderWindowsDYLD::DidLaunch() +void +DynamicLoaderWindowsDYLD::DidLaunch() { - } -Error DynamicLoaderWindowsDYLD::CanLoadImage() +Error +DynamicLoaderWindowsDYLD::CanLoadImage() { return Error(); } -ConstString DynamicLoaderWindowsDYLD::GetPluginName() +ConstString +DynamicLoaderWindowsDYLD::GetPluginName() { return GetPluginNameStatic(); } -uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() +uint32_t +DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h index d12b999f4627..8c479819c535 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===// +//===-- DynamicLoaderWindowsDYLD.h ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,9 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ -#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ +#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/lldb-forward.h" #include "lldb/Target/DynamicLoader.h" @@ -18,9 +22,10 @@ namespace lldb_private class DynamicLoaderWindowsDYLD : public DynamicLoader { - public: +public: DynamicLoaderWindowsDYLD(Process *process); - virtual ~DynamicLoaderWindowsDYLD(); + + ~DynamicLoaderWindowsDYLD() override; static void Initialize(); static void Terminate(); @@ -29,15 +34,15 @@ class DynamicLoaderWindowsDYLD : public DynamicLoader static DynamicLoader *CreateInstance(Process *process, bool force); - void DidAttach () override; - void DidLaunch () override; - Error CanLoadImage () override; + void DidAttach() override; + void DidLaunch() override; + Error CanLoadImage() override; lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override; ConstString GetPluginName() override; uint32_t GetPluginVersion() override; }; -} +} // namespace lldb_private -#endif +#endif // liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp new file mode 100644 index 000000000000..976310610f51 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -0,0 +1,134 @@ +//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTDumper.h" + +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace lldb_private; + +ASTDumper::ASTDumper (clang::Decl *decl) +{ + clang::DeclContext *decl_ctx = llvm::dyn_cast(decl); + + bool has_external_lexical_storage; + bool has_external_visible_storage; + + if (decl_ctx) + { + has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); + decl_ctx->setHasExternalLexicalStorage(false); + decl_ctx->setHasExternalVisibleStorage(false); + } + + llvm::raw_string_ostream os(m_dump); + decl->print (os); + os.flush(); + + if (decl_ctx) + { + decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); + decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); + } +} + +ASTDumper::ASTDumper (clang::DeclContext *decl_ctx) +{ + bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); + + decl_ctx->setHasExternalLexicalStorage(false); + decl_ctx->setHasExternalVisibleStorage(false); + + if (clang::Decl *decl = llvm::dyn_cast(decl_ctx)) + { + llvm::raw_string_ostream os(m_dump); + decl->print (os); + os.flush(); + } + else + { + m_dump.assign(""); + } + + decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); + decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); +} + +ASTDumper::ASTDumper (const clang::Type *type) +{ + m_dump = clang::QualType(type, 0).getAsString(); +} + +ASTDumper::ASTDumper (clang::QualType type) +{ + m_dump = type.getAsString(); +} + +ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type) +{ + m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); +} + +ASTDumper::ASTDumper (const CompilerType &compiler_type) +{ + m_dump = ClangASTContext::GetQualType(compiler_type).getAsString(); +} + + +const char * +ASTDumper::GetCString() +{ + return m_dump.c_str(); +} + +void ASTDumper::ToSTDERR() +{ + fprintf(stderr, "%s\n", m_dump.c_str()); +} + +void ASTDumper::ToLog(Log *log, const char *prefix) +{ + size_t len = m_dump.length() + 1; + + char *alloc = (char*)malloc(len); + char *str = alloc; + + memcpy(str, m_dump.c_str(), len); + + char *end = NULL; + + end = strchr(str, '\n'); + + while (end) + { + *end = '\0'; + + log->Printf("%s%s", prefix, str); + + *end = '\n'; + + str = end + 1; + end = strchr(str, '\n'); + } + + log->Printf("%s%s", prefix, str); + + free(alloc); +} + +void ASTDumper::ToStream(lldb::StreamSP &stream) +{ + stream->PutCString(m_dump.c_str()); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/source/Plugins/ExpressionParser/Clang/ASTDumper.h new file mode 100644 index 000000000000..c8dc6847d6c2 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.h @@ -0,0 +1,42 @@ +//===-- ASTDumper.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_ASTDumper_h_ +#define liblldb_ASTDumper_h_ + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/TypeVisitor.h" + +#include "lldb/Core/Stream.h" +#include "llvm/ADT/DenseSet.h" + +namespace lldb_private +{ + +class ASTDumper +{ +public: + ASTDumper (clang::Decl *decl); + ASTDumper (clang::DeclContext *decl_ctx); + ASTDumper (const clang::Type *type); + ASTDumper (clang::QualType type); + ASTDumper (lldb::opaque_compiler_type_t type); + ASTDumper (const CompilerType &compiler_type); + + const char *GetCString(); + void ToSTDERR(); + void ToLog(Log *log, const char *prefix); + void ToStream(lldb::StreamSP &stream); +private: + std::string m_dump; +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp new file mode 100644 index 000000000000..02505bde240c --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -0,0 +1,514 @@ +//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTResultSynthesizer.h" + +#include "ClangPersistentVariables.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Target/Target.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, + Target &target) : + m_ast_context (NULL), + m_passthrough (passthrough), + m_passthrough_sema (NULL), + m_target (target), + m_sema (NULL) +{ + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast(passthrough); +} + +ASTResultSynthesizer::~ASTResultSynthesizer() +{ +} + +void +ASTResultSynthesizer::Initialize(ASTContext &Context) +{ + m_ast_context = &Context; + + if (m_passthrough) + m_passthrough->Initialize(Context); +} + +void +ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (NamedDecl *named_decl = dyn_cast(D)) + { + if (log && log->GetVerbose()) + { + if (named_decl->getIdentifier()) + log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart()); + else if (ObjCMethodDecl *method_decl = dyn_cast(D)) + log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str()); + else + log->Printf("TransformTopLevelDecl()"); + } + + } + + if (LinkageSpecDecl *linkage_spec_decl = dyn_cast(D)) + { + RecordDecl::decl_iterator decl_iterator; + + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); + ++decl_iterator) + { + TransformTopLevelDecl(*decl_iterator); + } + } + else if (ObjCMethodDecl *method_decl = dyn_cast(D)) + { + if (m_ast_context && + !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) + { + RecordPersistentTypes(method_decl); + SynthesizeObjCMethodResult(method_decl); + } + } + else if (FunctionDecl *function_decl = dyn_cast(D)) + { + if (m_ast_context && + !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) + { + RecordPersistentTypes(function_decl); + SynthesizeFunctionResult(function_decl); + } + } +} + +bool +ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) +{ + DeclGroupRef::iterator decl_iterator; + + for (decl_iterator = D.begin(); + decl_iterator != D.end(); + ++decl_iterator) + { + Decl *decl = *decl_iterator; + + TransformTopLevelDecl(decl); + } + + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; +} + +bool +ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_sema) + return false; + + FunctionDecl *function_decl = FunDecl; + + if (!function_decl) + return false; + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf ("Untransformed function AST:\n%s", s.c_str()); + } + + Stmt *function_body = function_decl->getBody(); + CompoundStmt *compound_stmt = dyn_cast(function_body); + + bool ret = SynthesizeBodyResult (compound_stmt, + function_decl); + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf ("Transformed function AST:\n%s", s.c_str()); + } + + return ret; +} + +bool +ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_sema) + return false; + + if (!MethodDecl) + return false; + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + MethodDecl->print(os); + + os.flush(); + + log->Printf ("Untransformed method AST:\n%s", s.c_str()); + } + + Stmt *method_body = MethodDecl->getBody(); + + if (!method_body) + return false; + + CompoundStmt *compound_stmt = dyn_cast(method_body); + + bool ret = SynthesizeBodyResult (compound_stmt, + MethodDecl); + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + MethodDecl->print(os); + + os.flush(); + + log->Printf("Transformed method AST:\n%s", s.c_str()); + } + + return ret; +} + +bool +ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, + DeclContext *DC) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ASTContext &Ctx(*m_ast_context); + + if (!Body) + return false; + + if (Body->body_empty()) + return false; + + Stmt **last_stmt_ptr = Body->body_end() - 1; + Stmt *last_stmt = *last_stmt_ptr; + + while (dyn_cast(last_stmt)) + { + if (last_stmt_ptr != Body->body_begin()) + { + last_stmt_ptr--; + last_stmt = *last_stmt_ptr; + } + else + { + return false; + } + } + + Expr *last_expr = dyn_cast(last_stmt); + + if (!last_expr) + // No auxiliary variable necessary; expression returns void + return true; + + // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the + // case. + + do { + ImplicitCastExpr *implicit_cast = dyn_cast(last_expr); + + if (!implicit_cast) + break; + + if (implicit_cast->getCastKind() != CK_LValueToRValue) + break; + + last_expr = implicit_cast->getSubExpr(); + } while (0); + + // is_lvalue is used to record whether the expression returns an assignable Lvalue or an + // Rvalue. This is relevant because they are handled differently. + // + // For Lvalues + // + // - In AST result synthesis (here!) the expression E is transformed into an initialization + // T *$__lldb_expr_result_ptr = &E. + // + // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be + // passed into the expression. + // + // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at + // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent + // variables are treated similarly, having been materialized as references, but in those + // cases the value of the reference itself is never modified.) + // + // - During materialization, $0 (the result persistent variable) is ignored. + // + // - During dematerialization, $0 is marked up as a load address with value equal to the + // contents of the structure entry. + // + // For Rvalues + // + // - In AST result synthesis the expression E is transformed into an initialization + // static T $__lldb_expr_result = E. + // + // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be + // passed into the expression. + // + // - In IR transformations, an instruction is inserted at the beginning of the function to + // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result + // are redirected at that dereferenced version. Guard variables for the static variable + // are excised. + // + // - During materialization, $0 (the result persistent variable) is populated with the location + // of a newly-allocated area of memory. + // + // - During dematerialization, $0 is ignored. + + bool is_lvalue = + (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) && + (last_expr->getObjectKind() == OK_Ordinary); + + QualType expr_qual_type = last_expr->getType(); + const clang::Type *expr_type = expr_qual_type.getTypePtr(); + + if (!expr_type) + return false; + + if (expr_type->isVoidType()) + return true; + + if (log) + { + std::string s = expr_qual_type.getAsString(); + + log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + } + + clang::VarDecl *result_decl = NULL; + + if (is_lvalue) + { + IdentifierInfo *result_ptr_id; + + if (expr_type->isFunctionType()) + result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers + else + result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); + + m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type); + + QualType ptr_qual_type; + + if (expr_qual_type->getAs() != NULL) + ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); + else + ptr_qual_type = Ctx.getPointerType(expr_qual_type); + + result_decl = VarDecl::Create(Ctx, + DC, + SourceLocation(), + SourceLocation(), + result_ptr_id, + ptr_qual_type, + NULL, + SC_Static); + + if (!result_decl) + return false; + + ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); + + m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); + } + else + { + IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); + + result_decl = VarDecl::Create(Ctx, + DC, + SourceLocation(), + SourceLocation(), + &result_id, + expr_qual_type, + NULL, + SC_Static); + + if (!result_decl) + return false; + + m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); + } + + DC->addDecl(result_decl); + + /////////////////////////////// + // call AddInitializerToDecl + // + + //m_sema->AddInitializerToDecl(result_decl, last_expr); + + ///////////////////////////////// + // call ConvertDeclToDeclGroup + // + + Sema::DeclGroupPtrTy result_decl_group_ptr; + + result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); + + //////////////////////// + // call ActOnDeclStmt + // + + StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr, + SourceLocation(), + SourceLocation())); + + //////////////////////////////////////////////// + // replace the old statement with the new one + // + + *last_stmt_ptr = reinterpret_cast(result_initialization_stmt_result.get()); + + return true; +} + +void +ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) +{ + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) +{ + typedef DeclContext::specific_decl_iterator TypeDeclIterator; + + for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), + e = TypeDeclIterator(FunDeclCtx->decls_end()); + i != e; + ++i) + { + MaybeRecordPersistentType(*i); + } +} + +void +ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) +{ + if (!D->getIdentifier()) + return; + + StringRef name = D->getName(); + + if (name.size() == 0 || name[0] != '$') + return; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ConstString name_cs(name.str().c_str()); + + if (log) + log->Printf ("Recording persistent type %s\n", name_cs.GetCString()); + + Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(), + m_ast_context, + D); + + if (TypeDecl *TypeDecl_scratch = dyn_cast(D_scratch)) + llvm::cast(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch); +} + +void +ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) +{ + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) +{ + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) +{ + if (m_passthrough) + m_passthrough->HandleVTable(RD); +} + +void +ASTResultSynthesizer::PrintStats() +{ + if (m_passthrough) + m_passthrough->PrintStats(); +} + +void +ASTResultSynthesizer::InitializeSema(Sema &S) +{ + m_sema = &S; + + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); +} + +void +ASTResultSynthesizer::ForgetSema() +{ + m_sema = NULL; + + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h new file mode 100644 index 000000000000..9f7bbe05b082 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -0,0 +1,185 @@ +//===-- ASTResultSynthesizer.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_ASTResultSynthesizer_h_ +#define liblldb_ASTResultSynthesizer_h_ + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Target/Target.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" +/// @brief Adds a result variable declaration to the ASTs for an expression. +/// +/// Users expect the expression "i + 3" to return a result, even if a result +/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds +/// a result variable to the expression, transforming it to +/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the +/// resulting variable is mapped to the right piece of memory. +/// ASTResultSynthesizer's job is to add the variable and its initialization to +/// the ASTs for the expression, and it does so by acting as a SemaConsumer for +/// Clang. +//---------------------------------------------------------------------- +class ASTResultSynthesizer : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] target + /// The target, which contains the persistent variable store and the + /// AST importer. + //---------------------------------------------------------------------- + ASTResultSynthesizer(clang::ASTConsumer *passthrough, + Target &target); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTResultSynthesizer() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; + +private: + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing + /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on + /// anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void TransformTopLevelDecl(clang::Decl *D); + + //---------------------------------------------------------------------- + /// Process an Objective-C method and produce the result variable and + /// initialization + /// + /// @param[in] MethodDecl + /// The method to process. + //---------------------------------------------------------------------- + bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); + + //---------------------------------------------------------------------- + /// Process a function and produce the result variable and initialization + /// + /// @param[in] FunDecl + /// The function to process. + //---------------------------------------------------------------------- + bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); + + //---------------------------------------------------------------------- + /// Process a function body and produce the result variable and + /// initialization + /// + /// @param[in] Body + /// The body of the function. + /// + /// @param[in] DC + /// The DeclContext of the function, into which the result variable + /// is inserted. + //---------------------------------------------------------------------- + bool SynthesizeBodyResult(clang::CompoundStmt *Body, + clang::DeclContext *DC); + + //---------------------------------------------------------------------- + /// Given a DeclContext for a function or method, find all types + /// declared in the context and record any persistent types found. + /// + /// @param[in] FunDeclCtx + /// The context for the function to process. + //---------------------------------------------------------------------- + void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); + + //---------------------------------------------------------------------- + /// Given a TypeDecl, if it declares a type whose name starts with a + /// dollar sign, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void MaybeRecordPersistentType(clang::TypeDecl *D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + Target &m_target; ///< The target, which contains the persistent variable store and the + clang::Sema *m_sema; ///< The Sema to use. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTResultSynthesizer_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp new file mode 100644 index 000000000000..38a2b6b33a8a --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -0,0 +1,221 @@ +//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTStructExtractor.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, + const char *struct_name, + ClangFunctionCaller &function) : + m_ast_context (NULL), + m_passthrough (passthrough), + m_passthrough_sema (NULL), + m_sema (NULL), + m_action (NULL), + m_function (function), + m_struct_name (struct_name) +{ + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast(passthrough); +} + +ASTStructExtractor::~ASTStructExtractor() +{ +} + +void +ASTStructExtractor::Initialize(ASTContext &Context) +{ + m_ast_context = &Context; + + if (m_passthrough) + m_passthrough->Initialize(Context); +} + +void +ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) +{ + if (!F->hasBody()) + return; + + Stmt *body_stmt = F->getBody(); + CompoundStmt *body_compound_stmt = dyn_cast(body_stmt); + + if (!body_compound_stmt) + return; // do we have to handle this? + + RecordDecl *struct_decl = NULL; + + StringRef desired_name(m_struct_name.c_str()); + + for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); + bi != be; + ++bi) + { + Stmt *curr_stmt = *bi; + DeclStmt *curr_decl_stmt = dyn_cast(curr_stmt); + if (!curr_decl_stmt) + continue; + DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); + for (Decl *candidate_decl : decl_group) + { + RecordDecl *candidate_record_decl = dyn_cast(candidate_decl); + if (!candidate_record_decl) + continue; + if (candidate_record_decl->getName() == desired_name) + { + struct_decl = candidate_record_decl; + break; + } + } + if (struct_decl) + break; + } + + if (!struct_decl) + return; + + const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); + + if (!struct_layout) + return; + + m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits + m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; + m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; + + for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); + field_index < num_fields; + ++field_index) + { + m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); + } + + m_function.m_struct_valid = true; +} + +void +ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) +{ + LinkageSpecDecl *linkage_spec_decl = dyn_cast(D); + + if (linkage_spec_decl) + { + RecordDecl::decl_iterator decl_iterator; + + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); + ++decl_iterator) + { + ExtractFromTopLevelDecl(*decl_iterator); + } + } + + FunctionDecl *function_decl = dyn_cast(D); + + if (m_ast_context && + function_decl && + !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) + { + ExtractFromFunctionDecl(function_decl); + } +} + +bool +ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) +{ + DeclGroupRef::iterator decl_iterator; + + for (decl_iterator = D.begin(); + decl_iterator != D.end(); + ++decl_iterator) + { + Decl *decl = *decl_iterator; + + ExtractFromTopLevelDecl(decl); + } + + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; +} + +void +ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) +{ + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) +{ + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) +{ + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) +{ + if (m_passthrough) + m_passthrough->HandleVTable(RD); +} + +void +ASTStructExtractor::PrintStats() +{ + if (m_passthrough) + m_passthrough->PrintStats(); +} + +void +ASTStructExtractor::InitializeSema(Sema &S) +{ + m_sema = &S; + m_action = reinterpret_cast(m_sema); + + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); +} + +void +ASTStructExtractor::ForgetSema() +{ + m_sema = NULL; + m_action = NULL; + + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h new file mode 100644 index 000000000000..2152cff911ff --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -0,0 +1,158 @@ +//===-- ASTStructExtractor.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_ASTStructExtractor_h_ +#define liblldb_ASTStructExtractor_h_ + +#include "ClangExpressionVariable.h" +#include "ClangFunctionCaller.h" + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" +/// @brief Extracts and describes the argument structure for a wrapped function. +/// +/// This pass integrates with ClangFunctionCaller, which calls functions with custom +/// sets of arguments. To avoid having to implement the full calling convention +/// for the target's architecture, ClangFunctionCaller writes a simple wrapper +/// function that takes a pointer to an argument structure that contains room +/// for the address of the function to be called, the values of all its +/// arguments, and room for the function's return value. +/// +/// The definition of this struct is itself in the body of the wrapper function, +/// so Clang does the structure layout itself. ASTStructExtractor reads through +/// the AST for the wrapper function and finds the struct. +//---------------------------------------------------------------------- +class ASTStructExtractor : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] struct_name + /// The name of the structure to extract from the wrapper function. + /// + /// @param[in] function + /// The caller object whose members should be populated with information + /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor + /// for this purpose. + //---------------------------------------------------------------------- + ASTStructExtractor(clang::ASTConsumer *passthrough, + const char *struct_name, + ClangFunctionCaller &function); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTStructExtractor() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; + +private: + //---------------------------------------------------------------------- + /// Hunt the given FunctionDecl for the argument struct and place + /// information about it into m_function + /// + /// @param[in] F + /// The FunctionDecl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromFunctionDecl(clang::FunctionDecl* F); + + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named the same as the wrapper + /// function name, recursing as necessary through LinkageSpecDecls, and + /// calling ExtractFromFunctionDecl on anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromTopLevelDecl(clang::Decl* D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + clang::Sema *m_sema; ///< The Sema to use. + clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable. + + ClangFunctionCaller &m_function; ///< The function to populate with information about the argument structure. + std::string m_struct_name; ///< The name of the structure to extract. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTStructExtractor_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp new file mode 100644 index 000000000000..d2ea4390560a --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -0,0 +1,2101 @@ +//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangASTSource.h" + +#include "ASTDumper.h" +#include "ClangModulesDeclVendor.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +#include + +using namespace clang; +using namespace lldb_private; + +//------------------------------------------------------------------ +// Scoped class that will remove an active lexical decl from the set +// when it goes out of scope. +//------------------------------------------------------------------ +namespace { + class ScopedLexicalDeclEraser + { + public: + ScopedLexicalDeclEraser(std::set &decls, + const clang::Decl *decl) + : m_active_lexical_decls(decls), m_decl(decl) + { + } + + ~ScopedLexicalDeclEraser() + { + m_active_lexical_decls.erase(m_decl); + } + + private: + std::set &m_active_lexical_decls; + const clang::Decl *m_decl; + }; +} + +ClangASTSource::~ClangASTSource() +{ + m_ast_importer_sp->ForgetDestination(m_ast_context); + + // We are in the process of destruction, don't create clang ast context on demand + // by passing false to Target::GetScratchClangASTContext(create_on_demand). + ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); + + if (!scratch_clang_ast_context) + return; + + clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + + if (!scratch_ast_context) + return; + + if (m_ast_context != scratch_ast_context) + m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); +} + +void +ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) +{ + if (!m_ast_context) + return; + + m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); + m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); +} + +// The core lookup interface. +bool +ClangASTSource::FindExternalVisibleDeclsByName +( + const DeclContext *decl_ctx, + DeclarationName clang_decl_name +) +{ + if (!m_ast_context) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + if (GetImportInProgress()) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + std::string decl_name (clang_decl_name.getAsString()); + +// if (m_decl_map.DoingASTImport ()) +// return DeclContext::lookup_result(); +// + switch (clang_decl_name.getNameKind()) { + // Normal identifiers. + case DeclarationName::Identifier: + { + clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo(); + + if (!identifier_info || + identifier_info->getBuiltinID() != 0) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + } + break; + + // Operator names. + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + break; + + // Using directives found in this context. + // Tell Sema we didn't find any or we'll end up getting asked a *lot*. + case DeclarationName::CXXUsingDirective: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + { + llvm::SmallVector method_decls; + + NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx); + + FindObjCMethodDecls(method_search_context); + + SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls); + return (method_decls.size() > 0); + } + // These aren't possible in the global context. + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + + if (!GetLookupsEnabled()) + { + // Wait until we see a '$' at the start of a name before we start doing + // any lookups so we can avoid lookup up all of the builtin types. + if (!decl_name.empty() && decl_name[0] == '$') + { + SetLookupsEnabled (true); + } + else + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + } + + ConstString const_decl_name(decl_name.c_str()); + + const char *uniqued_const_decl_name = const_decl_name.GetCString(); + if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end()) + { + // We are currently looking up this name... + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + m_active_lookups.insert(uniqued_const_decl_name); +// static uint32_t g_depth = 0; +// ++g_depth; +// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name); + llvm::SmallVector name_decls; + NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx); + FindExternalVisibleDecls(name_search_context); + SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls); +// --g_depth; + m_active_lookups.erase (uniqued_const_decl_name); + return (name_decls.size() != 0); +} + +void +ClangASTSource::CompleteType (TagDecl *tag_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s", + current_id, static_cast(m_ast_context), + static_cast(tag_decl), + tag_decl->getName().str().c_str()); + + log->Printf(" CTD[%u] Before:", current_id); + ASTDumper dumper((Decl*)tag_decl); + dumper.ToLog(log, " [CTD] "); + } + + auto iter = m_active_lexical_decls.find(tag_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(tag_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + + if (!m_ast_importer_sp->CompleteTagDecl (tag_decl)) + { + // We couldn't complete the type. Maybe there's a definition + // somewhere else that can be completed. + + if (log) + log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id); + + bool found = false; + + DeclContext *decl_ctx = tag_decl->getDeclContext(); + + if (const NamespaceDecl *namespace_context = dyn_cast(decl_ctx)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast(namespace_map.get()), + static_cast(namespace_map->size())); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e && !found; + ++i) + { + if (log) + log->Printf(" CTD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + TypeList types; + + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); + + i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); + + for (uint32_t ti = 0, te = types.GetSize(); + ti != te && !found; + ++ti) + { + lldb::TypeSP type = types.GetTypeAtIndex(ti); + + if (!type) + continue; + + CompilerType clang_type (type->GetFullCompilerType ()); + + if (!clang_type) + continue; + + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + + if (!tag_type) + continue; + + TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); + + if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) + found = true; + } + } + } + else + { + TypeList types; + + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); + CompilerDeclContext namespace_decl; + + const ModuleList &module_list = m_target->GetImages(); + + bool exact_match = false; + module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types); + + for (uint32_t ti = 0, te = types.GetSize(); + ti != te && !found; + ++ti) + { + lldb::TypeSP type = types.GetTypeAtIndex(ti); + + if (!type) + continue; + + CompilerType clang_type (type->GetFullCompilerType ()); + + if (!clang_type) + continue; + + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + + if (!tag_type) + continue; + + TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); + + // We have found a type by basename and we need to make sure the decl contexts + // are the same before we can try to complete this type with another + if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl)) + continue; + + if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) + found = true; + } + } + } + + if (log) + { + log->Printf(" [CTD] After:"); + ASTDumper dumper((Decl*)tag_decl); + dumper.ToLog(log, " [CTD] "); + } +} + +void +ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", + static_cast(m_ast_context), + interface_decl->getName().str().c_str()); + log->Printf(" [COID] Before:"); + ASTDumper dumper((Decl*)interface_decl); + dumper.ToLog(log, " [COID] "); + } + + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) + { + if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) + { + ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) + { + m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl); + } + } + } + + m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl); + + if (interface_decl->getSuperClass() && + interface_decl->getSuperClass() != interface_decl) + CompleteType(interface_decl->getSuperClass()); + + if (log) + { + log->Printf(" [COID] After:"); + ASTDumper dumper((Decl*)interface_decl); + dumper.ToLog(log, " [COID] "); + } +} + +clang::ObjCInterfaceDecl * +ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl) +{ + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + return NULL; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + return NULL; + + ConstString class_name(interface_decl->getNameAsString().c_str()); + + lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + + if (!complete_type_sp) + return NULL; + + TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ()); + lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + + if (!complete_opaque_type) + return NULL; + + const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); + const ObjCInterfaceType *complete_interface_type = dyn_cast(complete_clang_type); + + if (!complete_interface_type) + return NULL; + + ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); + + return complete_iface_decl; +} + +void +ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, + llvm::function_ref predicate, + llvm::SmallVectorImpl &decls) +{ + ClangASTMetrics::RegisterLexicalQuery(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + const Decl *context_decl = dyn_cast(decl_context); + + if (!context_decl) + return; + + auto iter = m_active_lexical_decls.find(context_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(context_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", + current_id, static_cast(m_ast_context), + context_named_decl->getNameAsString().c_str(), + context_decl->getDeclKindName(), + static_cast(context_decl)); + else if(context_decl) + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", + current_id, static_cast(m_ast_context), + context_decl->getDeclKindName(), + static_cast(context_decl)); + else + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", + current_id, static_cast(m_ast_context)); + } + + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) + return; + + if (log) + { + log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", + current_id, static_cast(original_ctx), + static_cast(original_decl)); + ASTDumper(original_decl).ToLog(log, " "); + } + + if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) + { + ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) + { + original_decl = complete_iface_decl; + original_ctx = &complete_iface_decl->getASTContext(); + + m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl); + } + } + + if (TagDecl *original_tag_decl = dyn_cast(original_decl)) + { + ExternalASTSource *external_source = original_ctx->getExternalSource(); + + if (external_source) + external_source->CompleteType (original_tag_decl); + } + + const DeclContext *original_decl_context = dyn_cast(original_decl); + + if (!original_decl_context) + return; + + for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); + iter != original_decl_context->decls_end(); + ++iter) + { + Decl *decl = *iter; + + if (predicate(decl->getKind())) + { + if (log) + { + ASTDumper ast_dumper(decl); + if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) + log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString()); + else + log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); + } + + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + + if (!copied_decl) + continue; + + if (FieldDecl *copied_field = dyn_cast(copied_decl)) + { + QualType copied_field_type = copied_field->getType(); + + m_ast_importer_sp->RequireCompleteType(copied_field_type); + } + + DeclContext *decl_context_non_const = const_cast(decl_context); + + if (copied_decl->getDeclContext() != decl_context) + { + if (copied_decl->getDeclContext()->containsDecl(copied_decl)) + copied_decl->getDeclContext()->removeDecl(copied_decl); + copied_decl->setDeclContext(decl_context_non_const); + } + + if (!decl_context_non_const->containsDecl(copied_decl)) + decl_context_non_const->addDeclInternal(copied_decl); + } + } + + return; +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) +{ + assert (m_ast_context); + + ClangASTMetrics::RegisterVisibleQuery(); + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (!context.m_decl_context) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", + current_id, static_cast(m_ast_context), + name.GetCString()); + else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", + current_id, static_cast(m_ast_context), + name.GetCString(), + context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", + current_id, static_cast(m_ast_context), + name.GetCString(), + context.m_decl_context->getDeclKindName()); + } + + context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); + + if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast(namespace_map.get()), + static_cast(namespace_map->size())); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e; + ++i) + { + if (log) + log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, + i->first, + i->second, + current_id); + } + } + else if (isa(context.m_decl_context)) + { + FindObjCPropertyAndIvarDecls(context); + } + else if (!isa(context.m_decl_context)) + { + // we shouldn't be getting FindExternalVisibleDecls calls for these + return; + } + else + { + CompilerDeclContext namespace_decl; + + if (log) + log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); + + FindExternalVisibleDecls(context, + lldb::ModuleSP(), + namespace_decl, + current_id); + } + + if (!context.m_namespace_map->empty()) + { + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", + current_id, + static_cast(context.m_namespace_map.get()), + static_cast(context.m_namespace_map->size())); + + NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); + + if (clang_namespace_decl) + clang_namespace_decl->setHasExternalVisibleStorage(); + } +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, + unsigned int current_id) +{ + assert (m_ast_context); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SymbolContextList sc_list; + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + const char *name_unique_cstr = name.GetCString(); + + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + + if (name_unique_cstr == NULL) + return; + + // The ClangASTSource is not responsible for finding $-names. + if (name_unique_cstr[0] == '$') + return; + + if (module_sp && namespace_decl) + { + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + + if (symbol_vendor) + { + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + + if (found_namespace_decl) + { + context.m_namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); + + if (log) + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + } + } + } + else + { + const ModuleList &target_images = m_target->GetImages(); + Mutex::Locker modules_locker (target_images.GetMutex()); + + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) + { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + + if (!image) + continue; + + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + + if (found_namespace_decl) + { + context.m_namespace_map->push_back(std::pair(image, found_namespace_decl)); + + if (log) + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); + } + } + } + + do + { + TypeList types; + SymbolContext null_sc; + const bool exact_match = false; + + if (module_sp && namespace_decl) + module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); + else + m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); + + bool found_a_type = false; + + if (size_t num_types = types.GetSize()) + { + for (size_t ti = 0; ti < num_types; ++ti) + { + lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); + + if (log) + { + const char *name_string = type_sp->GetName().GetCString(); + + log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", + current_id, + name.GetCString(), + (name_string ? name_string : "")); + } + + CompilerType full_type = type_sp->GetFullCompilerType(); + + CompilerType copied_clang_type (GuardedCopyType(full_type)); + + if (!copied_clang_type) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type", + current_id); + + continue; + } + + context.AddTypeDecl(copied_clang_type); + + found_a_type = true; + break; + } + } + + if (!found_a_type) + { + // Try the modules next. + + do + { + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules)) + { + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_named_decl); + + found_a_type = true; + } + } + } while (0); + } + + if (!found_a_type) + { + do + { + // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", + current_id); + + break; + } + + context.AddNamedDecl(copied_named_decl); + } + while(0); + } + + } while(0); +} + +template class TaggedASTDecl { +public: + TaggedASTDecl() : decl(NULL) { } + TaggedASTDecl(D *_decl) : decl(_decl) { } + bool IsValid() const { return (decl != NULL); } + bool IsInvalid() const { return !IsValid(); } + D *operator->() const { return decl; } + D *decl; +}; + +template class TD, class D1> +TD +DynCast(TD source) +{ + return TD (dyn_cast(source.decl)); +} + +template class DeclFromParser; +template class DeclFromUser; + +template class DeclFromParser : public TaggedASTDecl { +public: + DeclFromParser() : TaggedASTDecl() { } + DeclFromParser(D *_decl) : TaggedASTDecl(_decl) { } + + DeclFromUser GetOrigin(ClangASTImporter *importer); +}; + +template class DeclFromUser : public TaggedASTDecl { +public: + DeclFromUser() : TaggedASTDecl() { } + DeclFromUser(D *_decl) : TaggedASTDecl(_decl) { } + + DeclFromParser Import(ClangASTImporter *importer, ASTContext &dest_ctx); +}; + +template +DeclFromUser +DeclFromParser::GetOrigin(ClangASTImporter *importer) +{ + DeclFromUser <> origin_decl; + importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + if (origin_decl.IsInvalid()) + return DeclFromUser(); + return DeclFromUser(dyn_cast(origin_decl.decl)); +} + +template +DeclFromParser +DeclFromUser::Import(ClangASTImporter *importer, ASTContext &dest_ctx) +{ + DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); + if (parser_generic_decl.IsInvalid()) + return DeclFromParser(); + return DeclFromParser(dyn_cast(parser_generic_decl.decl)); +} + +static bool +FindObjCMethodDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + ObjCInterfaceDecl *original_interface_decl, + clang::ASTContext *ast_context, + ClangASTImporter *ast_importer, + const char *log_info) +{ + const DeclarationName &decl_name(context.m_decl_name); + clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); + + Selector original_selector; + + if (decl_name.isObjCZeroArgSelector()) + { + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); + original_selector = original_ctx->Selectors.getSelector(0, &ident); + } + else if (decl_name.isObjCOneArgSelector()) + { + const std::string &decl_name_string = decl_name.getAsString(); + std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); + original_selector = original_ctx->Selectors.getSelector(1, &ident); + } + else + { + SmallVector idents; + + clang::Selector sel = decl_name.getObjCSelector(); + + unsigned num_args = sel.getNumArgs(); + + for (unsigned i = 0; + i != num_args; + ++i) + { + idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); + } + + original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); + } + + DeclarationName original_decl_name(original_selector); + + llvm::SmallVector methods; + + ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); + + if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) + { + methods.push_back(instance_method_decl); + } + else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) + { + methods.push_back(class_method_decl); + } + + if (methods.empty()) + { + return false; + } + + for (NamedDecl *named_decl : methods) + { + if (!named_decl) + continue; + + ObjCMethodDecl *result_method = dyn_cast(named_decl); + + if (!result_method) + continue; + + Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); + + if (!copied_decl) + continue; + + ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); + + if (!copied_method_decl) + continue; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); + } + + return true; +} + +void +ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + const DeclarationName &decl_name(context.m_decl_name); + const DeclContext *decl_ctx(context.m_decl_context); + + const ObjCInterfaceDecl *interface_decl = dyn_cast(decl_ctx); + + if (!interface_decl) + return; + + do + { + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); + + if (!original_decl) + break; + + ObjCInterfaceDecl *original_interface_decl = dyn_cast(original_decl); + + if (FindObjCMethodDeclsWithOrigin(current_id, + context, + original_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "at origin")) + return; // found it, no need to look any further + } while (0); + + StreamString ss; + + if (decl_name.isObjCZeroArgSelector()) + { + ss.Printf("%s", decl_name.getAsString().c_str()); + } + else if (decl_name.isObjCOneArgSelector()) + { + ss.Printf("%s", decl_name.getAsString().c_str()); + } + else + { + clang::Selector sel = decl_name.getObjCSelector(); + + for (unsigned i = 0, e = sel.getNumArgs(); + i != e; + ++i) + { + llvm::StringRef r = sel.getNameForSlot(i); + ss.Printf("%s:", r.str().c_str()); + } + } + ss.Flush(); + + if (strstr(ss.GetData(), "$__lldb")) + return; // we don't need any results + + ConstString selector_name(ss.GetData()); + + if (log) + log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]", + current_id, static_cast(m_ast_context), + interface_decl->getNameAsString().c_str(), + selector_name.AsCString()); + SymbolContextList sc_list; + + const bool include_symbols = false; + const bool include_inlines = false; + const bool append = false; + + std::string interface_name = interface_decl->getNameAsString(); + + do + { + StreamString ms; + ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString instance_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + + if (sc_list.GetSize()) + break; + + ms.Clear(); + ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString class_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + + if (sc_list.GetSize()) + break; + + // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in + // categories on the desired class. + + SymbolContextList candidate_sc_list; + + m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list); + + for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); + ci != ce; + ++ci) + { + SymbolContext candidate_sc; + + if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) + continue; + + if (!candidate_sc.function) + continue; + + const char *candidate_name = candidate_sc.function->GetName().AsCString(); + + const char *cursor = candidate_name; + + if (*cursor != '+' && *cursor != '-') + continue; + + ++cursor; + + if (*cursor != '[') + continue; + + ++cursor; + + size_t interface_len = interface_name.length(); + + if (strncmp(cursor, interface_name.c_str(), interface_len)) + continue; + + cursor += interface_len; + + if (*cursor == ' ' || *cursor == '(') + sc_list.Append(candidate_sc); + } + } + while (0); + + if (sc_list.GetSize()) + { + // We found a good function symbol. Use that. + + for (uint32_t i = 0, e = sc_list.GetSize(); + i != e; + ++i) + { + SymbolContext sc; + + if (!sc_list.GetContextAtIndex(i, sc)) + continue; + + if (!sc.function) + continue; + + CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext(); + if (!function_decl_ctx) + continue; + + ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + + if (!method_decl) + continue; + + ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); + + if (!found_interface_decl) + continue; + + if (found_interface_decl->getName() == interface_decl->getName()) + { + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + + if (!copied_decl) + continue; + + ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); + + if (!copied_method_decl) + continue; + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); + } + } + + return; + } + + // Try the debug information. + + do + { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(interface_decl)); + + if (!complete_interface_decl) + break; + + // We found the complete interface. The runtime never needs to be queried in this scenario. + + DeclFromUser complete_iface_decl(complete_interface_decl); + + if (complete_interface_decl == interface_decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast(complete_interface_decl), + static_cast(&complete_iface_decl->getASTContext())); + + FindObjCMethodDeclsWithOrigin(current_id, + context, + complete_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "in debug info"); + + return; + } + while (0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(interface_name, + append, + max_matches, + decls)) + break; + + ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast(decls[0]); + + if (!interface_decl_from_modules) + break; + + if (FindObjCMethodDeclsWithOrigin(current_id, + context, + interface_decl_from_modules, + m_ast_context, + m_ast_importer_sp.get(), + "in modules")) + return; + } + } + while (0); + + do + { + // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(interface_name, + append, + max_matches, + decls)) + break; + + ObjCInterfaceDecl *runtime_interface_decl = dyn_cast(decls[0]); + + if (!runtime_interface_decl) + break; + + FindObjCMethodDeclsWithOrigin(current_id, + context, + runtime_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "in runtime"); + } + while(0); +} + +static bool +FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + clang::ASTContext &ast_context, + ClangASTImporter *ast_importer, + DeclFromUser &origin_iface_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (origin_iface_decl.IsInvalid()) + return false; + + std::string name_str = context.m_decl_name.getAsString(); + StringRef name(name_str.c_str()); + IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); + + DeclFromUser origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); + + bool found = false; + + if (origin_property_decl.IsValid()) + { + DeclFromParser parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); + if (parser_property_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_property_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_property_decl.decl); + found = true; + } + } + + DeclFromUser origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); + + if (origin_ivar_decl.IsValid()) + { + DeclFromParser parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); + if (parser_ivar_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_ivar_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_ivar_decl.decl); + found = true; + } + } + + return found; +} + +void +ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + DeclFromParser parser_iface_decl(cast(context.m_decl_context)); + DeclFromUser origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + + ConstString class_name(parser_iface_decl->getNameAsString().c_str()); + + if (log) + log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", + current_id, static_cast(m_ast_context), + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + origin_iface_decl)) + return; + + if (log) + log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", + current_id, static_cast(origin_iface_decl.decl), + static_cast(&origin_iface_decl->getASTContext())); + + SymbolContext null_sc; + TypeList type_list; + + do + { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(parser_iface_decl.decl)); + + if (!complete_interface_decl) + break; + + // We found the complete interface. The runtime never needs to be queried in this scenario. + + DeclFromUser complete_iface_decl(complete_interface_decl); + + if (complete_iface_decl.decl == origin_iface_decl.decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(complete_iface_decl.decl), + static_cast(&complete_iface_decl->getASTContext())); + + FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + complete_iface_decl); + + return; + } + while(0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); + + if (!modules_decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(class_name, + append, + max_matches, + decls)) + break; + + DeclFromUser interface_decl_from_modules(dyn_cast(decls[0])); + + if (!interface_decl_from_modules.IsValid()) + break; + + if (log) + log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(interface_decl_from_modules.decl), + static_cast(&interface_decl_from_modules->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + interface_decl_from_modules)) + return; + } + while(0); + + do + { + // Check the runtime only if the debug information didn't have a complete interface + // and nothing was in the modules. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + return; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + return; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(class_name, + append, + max_matches, + decls)) + break; + + DeclFromUser interface_decl_from_runtime(dyn_cast(decls[0])); + + if (!interface_decl_from_runtime.IsValid()) + break; + + if (log) + log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(interface_decl_from_runtime.decl), + static_cast(&interface_decl_from_runtime->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + interface_decl_from_runtime)) + return; + } + while(0); +} + +typedef llvm::DenseMap FieldOffsetMap; +typedef llvm::DenseMap BaseOffsetMap; + +template +static bool +ImportOffsetMap(llvm::DenseMap &destination_map, llvm::DenseMap &source_map, + ClangASTImporter *importer, ASTContext &dest_ctx) +{ + // When importing fields into a new record, clang has a hard requirement that + // fields be imported in field offset order. Since they are stored in a DenseMap + // with a pointer as the key type, this means we cannot simply iterate over the + // map, as the order will be non-deterministic. Instead we have to sort by the offset + // and then insert in sorted order. + typedef llvm::DenseMap MapType; + typedef typename MapType::value_type PairType; + std::vector 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; + }); + + for (const auto &item : sorted_items) + { + DeclFromUser user_decl(const_cast(item.first)); + DeclFromParser parser_decl(user_decl.Import(importer, dest_ctx)); + if (parser_decl.IsInvalid()) + return false; + destination_map.insert(std::pair(parser_decl.decl, item.second)); + } + + return true; +} + +template +bool +ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser &record, + BaseOffsetMap &base_offsets) +{ + for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), + be = (IsVirtual ? record->vbases_end() : record->bases_end()); + bi != be; ++bi) + { + if (!IsVirtual && bi->isVirtual()) + continue; + + const clang::Type *origin_base_type = bi->getType().getTypePtr(); + const clang::RecordType *origin_base_record_type = origin_base_type->getAs(); + + if (!origin_base_record_type) + return false; + + DeclFromUser origin_base_record(origin_base_record_type->getDecl()); + + if (origin_base_record.IsInvalid()) + return false; + + DeclFromUser origin_base_cxx_record(DynCast(origin_base_record)); + + if (origin_base_cxx_record.IsInvalid()) + return false; + + CharUnits base_offset; + + if (IsVirtual) + base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); + else + base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); + + base_offsets.insert(std::pair(origin_base_cxx_record.decl, base_offset)); + } + + return true; +} + +bool +ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, + FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, + BaseOffsetMap &virtual_base_offsets) +{ + ClangASTMetrics::RegisterRecordLayout(); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']", + current_id, static_cast(m_ast_context), + static_cast(record), + record->getNameAsString().c_str()); + + DeclFromParser parser_record(record); + DeclFromUser origin_record(parser_record.GetOrigin(m_ast_importer_sp.get())); + + if (origin_record.IsInvalid()) + return false; + + FieldOffsetMap origin_field_offsets; + BaseOffsetMap origin_base_offsets; + BaseOffsetMap origin_virtual_base_offsets; + + ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast(origin_record.decl)); + + clang::RecordDecl* definition = origin_record.decl->getDefinition(); + if (!definition || !definition->isCompleteDefinition()) + return false; + + const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); + + int field_idx = 0, field_count = record_layout.getFieldCount(); + + for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) + { + if (field_idx >= field_count) + return false; // Layout didn't go well. Bail out. + + uint64_t field_offset = record_layout.getFieldOffset(field_idx); + + origin_field_offsets.insert(std::pair(*fi, field_offset)); + + field_idx++; + } + + ASTContext &parser_ast_context(record->getASTContext()); + + DeclFromUser origin_cxx_record(DynCast(origin_record)); + + if (origin_cxx_record.IsValid()) + { + if (!ExtractBaseOffsets(record_layout, origin_cxx_record, origin_base_offsets) || + !ExtractBaseOffsets(record_layout, origin_cxx_record, origin_virtual_base_offsets)) + return false; + } + + if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context)) + return false; + + size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); + alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); + + if (log) + { + log->Printf("LRT[%u] returned:", current_id); + log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, + static_cast(origin_record.decl)); + log->Printf("LRT[%u] Size = %" PRId64, current_id, size); + log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); + log->Printf("LRT[%u] Fields:", current_id); + for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); + fi != fe; + ++fi) + { + log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, + static_cast(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); + } + DeclFromParser parser_cxx_record = DynCast(parser_record); + if (parser_cxx_record.IsValid()) + { + log->Printf("LRT[%u] Bases:", current_id); + for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); + bi != be; + ++bi) + { + bool is_virtual = bi->isVirtual(); + + QualType base_type = bi->getType(); + const RecordType *base_record_type = base_type->getAs(); + DeclFromParser base_record(base_record_type->getDecl()); + DeclFromParser base_cxx_record = DynCast(base_record); + + log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, + (is_virtual ? "Virtual " : ""), static_cast(base_cxx_record.decl), + base_cxx_record.decl->getNameAsString().c_str(), + (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() + : base_offsets[base_cxx_record.decl].getQuantity())); + } + } + else + { + log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + } + } + + return true; +} + +void +ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, + const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const +{ + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + if (parent_map && parent_map->size()) + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s", + current_id, static_cast(m_ast_context), + name.GetCString(), + parent_map->begin()->second.GetName().AsCString()); + else + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s", + current_id, static_cast(m_ast_context), + name.GetCString()); + } + + if (parent_map) + { + for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end(); + i != e; + ++i) + { + CompilerDeclContext found_namespace_decl; + + lldb::ModuleSP module_sp = i->first; + CompilerDeclContext module_parent_namespace_decl = i->second; + + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl); + + if (!found_namespace_decl) + continue; + + namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + } + } + else + { + const ModuleList &target_images = m_target->GetImages(); + Mutex::Locker modules_locker(target_images.GetMutex()); + + CompilerDeclContext null_namespace_decl; + + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) + { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + + if (!image) + continue; + + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); + + if (!found_namespace_decl) + continue; + + namespace_map->push_back(std::pair(image, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); + } + } +} + +NamespaceDecl * +ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) +{ + if (!namespace_decls) + return nullptr; + + const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second; + + clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl); + if (!src_ast) + return nullptr; + clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl); + + if (!src_namespace_decl) + return nullptr; + + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + + if (!copied_decl) + return nullptr; + + NamespaceDecl *copied_namespace_decl = dyn_cast(copied_decl); + + if (!copied_namespace_decl) + return nullptr; + + context.m_decls.push_back(copied_namespace_decl); + + m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls); + + return dyn_cast(copied_decl); +} + +CompilerType +ClangASTSource::GuardedCopyType (const CompilerType &src_type) +{ + ClangASTContext *src_ast = llvm::dyn_cast_or_null(src_type.GetTypeSystem()); + if (src_ast == nullptr) + return CompilerType(); + + ClangASTMetrics::RegisterLLDBImport(); + + SetImportInProgress(true); + + QualType copied_qual_type = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type)); + + SetImportInProgress(false); + + if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) + // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types + // on occasion. + return CompilerType(); + + return CompilerType(m_ast_context, copied_qual_type); +} + +clang::NamedDecl * +NameSearchContext::AddVarDecl(const CompilerType &type) +{ + assert (type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return NULL; + + ClangASTContext* lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; + + IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); + + clang::ASTContext *ast = lldb_ast->getASTContext(); + + clang::NamedDecl *Decl = VarDecl::Create(*ast, + const_cast(m_decl_context), + SourceLocation(), + SourceLocation(), + ii, + ClangASTContext::GetQualType(type), + 0, + SC_Static); + m_decls.push_back(Decl); + + return Decl; +} + +clang::NamedDecl * +NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c) +{ + assert (type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return NULL; + + if (m_function_types.count(type)) + return NULL; + + ClangASTContext* lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; + + m_function_types.insert(type); + + QualType qual_type (ClangASTContext::GetQualType(type)); + + clang::ASTContext *ast = lldb_ast->getASTContext(); + + const bool isInlineSpecified = false; + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; + + clang::DeclContext *context = const_cast(m_decl_context); + + if (extern_c) { + context = LinkageSpecDecl::Create(*ast, + context, + SourceLocation(), + SourceLocation(), + clang::LinkageSpecDecl::LanguageIDs::lang_c, + false); + } + + // Pass the identifier info for functions the decl_name is needed for operators + clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name; + + clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, + context, + SourceLocation(), + SourceLocation(), + decl_name, + qual_type, + NULL, + SC_Extern, + isInlineSpecified, + hasWrittenPrototype, + isConstexprSpecified); + + // We have to do more than just synthesize the FunctionDecl. We have to + // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do + // this, we raid the function's FunctionProtoType for types. + + const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs(); + + if (func_proto_type) + { + unsigned NumArgs = func_proto_type->getNumParams(); + unsigned ArgIndex; + + SmallVector parm_var_decls; + + for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) + { + QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); + + parm_var_decls.push_back(ParmVarDecl::Create (*ast, + const_cast(context), + SourceLocation(), + SourceLocation(), + NULL, + arg_qual_type, + NULL, + SC_Static, + NULL)); + } + + func_decl->setParams(ArrayRef(parm_var_decls)); + } + else + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("Function type wasn't a FunctionProtoType"); + } + + m_decls.push_back(func_decl); + + return func_decl; +} + +clang::NamedDecl * +NameSearchContext::AddGenericFunDecl() +{ + FunctionProtoType::ExtProtoInfo proto_info; + + proto_info.Variadic = true; + + QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result + ArrayRef(), // argument types + proto_info)); + + return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true); +} + +clang::NamedDecl * +NameSearchContext::AddTypeDecl(const CompilerType &clang_type) +{ + if (clang_type) + { + QualType qual_type = ClangASTContext::GetQualType(clang_type); + + if (const TypedefType *typedef_type = llvm::dyn_cast(qual_type)) + { + TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); + + m_decls.push_back(typedef_name_decl); + + return (NamedDecl*)typedef_name_decl; + } + else if (const TagType *tag_type = qual_type->getAs()) + { + TagDecl *tag_decl = tag_type->getDecl(); + + m_decls.push_back(tag_decl); + + return tag_decl; + } + else if (const ObjCObjectType *objc_object_type = qual_type->getAs()) + { + ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); + + m_decls.push_back((NamedDecl*)interface_decl); + + return (NamedDecl*)interface_decl; + } + } + return NULL; +} + +void +NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) +{ + for (clang::NamedDecl *decl : result) + m_decls.push_back (decl); +} + +void +NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) +{ + m_decls.push_back (decl); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h new file mode 100644 index 000000000000..bb6384721f51 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -0,0 +1,526 @@ +//===-- ClangASTSource.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_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types. Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource : + public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource (const lldb::TargetSP &target) : + m_import_in_progress (false), + m_lookups_enabled (false), + m_target (target), + m_ast_context (NULL), + m_active_lexical_decls (), + m_active_lookups () + { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource() override; + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } + clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } + uint32_t GetNumExternalSelectors () override { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override + { return NULL; } + void MaterializeVisibleDecls (const clang::DeclContext *DC) + { return; } + + void InstallASTContext (clang::ASTContext *ast_context) + { + m_ast_context = ast_context; + m_ast_importer_sp->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// A callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + void FindExternalLexicalDecls( + const clang::DeclContext *DC, llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl &Decls) override; + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override; + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::TagDecl *Tag) override; + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace (NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls (NameSearchContext &context); + + void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } + bool GetImportInProgress () { return m_import_in_progress; } + + void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } + bool GetLookupsEnabled () { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon + { + public: + ClangASTSourceProxy (ClangASTSource &original) : + m_original(original) + { + } + + bool + FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override + { + return m_original.FindExternalVisibleDeclsByName(DC, Name); + } + + void + FindExternalLexicalDecls(const clang::DeclContext *DC, + llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl &Decls) override + { + return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); + } + + void + CompleteType(clang::TagDecl *Tag) override + { + return m_original.CompleteType(Tag); + } + + void + CompleteType(clang::ObjCInterfaceDecl *Class) override + { + return m_original.CompleteType(Class); + } + + bool + layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } + + void + StartTranslationUnit(clang::ASTConsumer *Consumer) override + { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata * + GetMetadata(const void * object) + { + return m_original.GetMetadata(object); + } + + void + SetMetadata(const void * object, ClangASTMetadata &metadata) + { + return m_original.SetMetadata(object, metadata); + } + + bool + HasMetadata(const void * object) + { + return m_original.HasMetadata(object); + } + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() + { + return new ClangASTSourceProxy(*this); + } + +protected: + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCMethodDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCPropertyAndIvarDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] src_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + CompilerType + GuardedCopyType (const CompilerType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP m_target; ///< The target to use in finding variables and types. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::set m_active_lexical_decls; + std::set m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +/// +/// LLDB needs to create Decls for entities it finds. This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext (ClangASTSource &astSource, + llvm::SmallVectorImpl &decls, + clang::DeclarationName &name, + const clang::DeclContext *dc) : + m_ast_source(astSource), + m_decls(decls), + m_decl_name(name), + m_decl_context(dc) + { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const CompilerType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const CompilerType &type, + bool extern_c = false); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] compiler_type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); + + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult (clang::DeclContextLookupResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl (clang::NamedDecl *decl); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTSource_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp new file mode 100644 index 000000000000..c9bc4b6487cd --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -0,0 +1,2351 @@ +//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" + +#include "ASTDumper.h" +#include "ClangASTSource.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" + +using namespace lldb; +using namespace lldb_private; +using namespace clang; + +ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx) : + ClangASTSource (exe_ctx.GetTargetSP()), + m_found_entities (), + m_struct_members (), + m_keep_result_in_memory (keep_result_in_memory), + m_result_delegate (result_delegate), + m_parser_vars (), + m_struct_vars () +{ + EnableStructVars(); +} + +ClangExpressionDeclMap::~ClangExpressionDeclMap() +{ + // Note: The model is now that the parser's AST context and all associated + // data does not vanish until the expression has been executed. This means + // that valuable lookup data (like namespaces) doesn't vanish, but + + DidParse(); + DisableStructVars(); +} + +bool +ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, + Materializer *materializer) +{ + ClangASTMetrics::ClearLocalCounters(); + + EnableParserVars(); + m_parser_vars->m_exe_ctx = exe_ctx; + + Target *target = exe_ctx.GetTargetPtr(); + if (exe_ctx.GetFramePtr()) + m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); + else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) + m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); + else if (exe_ctx.GetProcessPtr()) + { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } + else if (target) + { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } + + if (target) + { + m_parser_vars->m_persistent_vars = llvm::cast(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); + + if (!target->GetScratchClangASTContext()) + return false; + } + + m_parser_vars->m_target_info = GetTargetInfo(); + m_parser_vars->m_materializer = materializer; + + return true; +} + +void +ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen) +{ + assert(m_parser_vars); + m_parser_vars->m_code_gen = code_gen; +} + +void +ClangExpressionDeclMap::DidParse() +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + ClangASTMetrics::DumpCounters(log); + + if (m_parser_vars.get()) + { + for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); + entity_index < num_entities; + ++entity_index) + { + ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index)); + if (var_sp) + llvm::cast(var_sp.get())->DisableParserVars(GetParserID()); + } + + for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize(); + pvar_index < num_pvars; + ++pvar_index) + { + ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); + if (ClangExpressionVariable *clang_var = llvm::dyn_cast(pvar_sp.get())) + clang_var->DisableParserVars(GetParserID()); + } + + DisableParserVars(); + } +} + +// Interface for IRForTarget + +ClangExpressionDeclMap::TargetInfo +ClangExpressionDeclMap::GetTargetInfo() +{ + assert (m_parser_vars.get()); + + TargetInfo ret; + + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + + Process *process = exe_ctx.GetProcessPtr(); + if (process) + { + ret.byte_order = process->GetByteOrder(); + ret.address_byte_size = process->GetAddressByteSize(); + } + else + { + Target *target = exe_ctx.GetTargetPtr(); + if (target) + { + ret.byte_order = target->GetArchitecture().GetByteOrder(); + ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); + } + } + + return ret; +} + +bool +ClangExpressionDeclMap::AddPersistentVariable +( + const NamedDecl *decl, + const ConstString &name, + TypeFromParser parser_type, + bool is_result, + bool is_lvalue +) +{ + assert (m_parser_vars.get()); + + ClangASTContext *ast = llvm::dyn_cast_or_null(parser_type.GetTypeSystem()); + if (ast == nullptr) + return false; + + if (m_parser_vars->m_materializer && is_result) + { + Error err; + + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == nullptr) + return false; + + ClangASTContext *context(target->GetScratchClangASTContext()); + + TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), + ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); + + uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, + is_lvalue, + m_keep_result_in_memory, + m_result_delegate, + err); + + ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(), + name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size); + + m_found_entities.AddNewlyConstructedVariable(var); + + var->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; + + var->EnableJITVars(GetParserID()); + + ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID()); + + jit_vars->m_offset = offset; + + return true; + } + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == NULL) + return false; + + ClangASTContext *context(target->GetScratchClangASTContext()); + + TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), + ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); + + if (!user_type.GetOpaqueQualType()) + { + if (log) + log->Printf("Persistent variable's type wasn't copied successfully"); + return false; + } + + if (!m_parser_vars->m_target_info.IsValid()) + return false; + + ClangExpressionVariable *var = llvm::cast(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (), + name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size).get()); + + if (!var) + return false; + + var->m_frozen_sp->SetHasCompleteType(); + + if (is_result) + var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; + else + var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist + + if (is_lvalue) + { + var->m_flags |= ClangExpressionVariable::EVIsProgramReference; + } + else + { + var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + } + + if (m_keep_result_in_memory) + { + var->m_flags |= ClangExpressionVariable::EVKeepInTarget; + } + + if (log) + log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + + var->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; + + return true; +} + +bool +ClangExpressionDeclMap::AddValueToStruct +( + const NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + lldb::offset_t alignment +) +{ + assert (m_struct_vars.get()); + assert (m_parser_vars.get()); + + bool is_persistent_variable = false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_struct_vars->m_struct_laid_out = false; + + if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID())) + return true; + + ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + + if (!var) + { + var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID()); + is_persistent_variable = true; + } + + if (!var) + return false; + + if (log) + log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", + static_cast(decl), name.GetCString(), + var->GetName().GetCString()); + + // We know entity->m_parser_vars is valid because we used a parser variable + // to find it + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(var)->GetParserVars(GetParserID()); + + parser_vars->m_llvm_value = value; + + if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast(var)->GetJITVars(GetParserID())) + { + // We already laid this out; do not touch + + if (log) + log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset); + } + + llvm::cast(var)->EnableJITVars(GetParserID()); + + ClangExpressionVariable::JITVars *jit_vars = llvm::cast(var)->GetJITVars(GetParserID()); + + jit_vars->m_alignment = alignment; + jit_vars->m_size = size; + + m_struct_members.AddVariable(var->shared_from_this()); + + if (m_parser_vars->m_materializer) + { + uint32_t offset = 0; + + Error err; + + if (is_persistent_variable) + { + ExpressionVariableSP var_sp(var->shared_from_this()); + offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err); + } + else + { + if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) + offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); + else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) + offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); + else if (parser_vars->m_lldb_var) + offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err); + } + + if (!err.Success()) + return false; + + if (log) + log->Printf("Placed at 0x%llx", (unsigned long long)offset); + + jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. + } + + return true; +} + +bool +ClangExpressionDeclMap::DoStructLayout () +{ + assert (m_struct_vars.get()); + + if (m_struct_vars->m_struct_laid_out) + return true; + + if (!m_parser_vars->m_materializer) + return false; + + m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment(); + m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize(); + m_struct_vars->m_struct_laid_out = true; + return true; +} + +bool ClangExpressionDeclMap::GetStructInfo +( + uint32_t &num_elements, + size_t &size, + lldb::offset_t &alignment +) +{ + assert (m_struct_vars.get()); + + if (!m_struct_vars->m_struct_laid_out) + return false; + + num_elements = m_struct_members.GetSize(); + size = m_struct_vars->m_struct_size; + alignment = m_struct_vars->m_struct_alignment; + + return true; +} + +bool +ClangExpressionDeclMap::GetStructElement +( + const NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index +) +{ + assert (m_struct_vars.get()); + + if (!m_struct_vars->m_struct_laid_out) + return false; + + if (index >= m_struct_members.GetSize()) + return false; + + ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); + + if (!member_sp) + return false; + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(member_sp.get())->GetParserVars(GetParserID()); + ClangExpressionVariable::JITVars *jit_vars = llvm::cast(member_sp.get())->GetJITVars(GetParserID()); + + if (!parser_vars || + !jit_vars || + !member_sp->GetValueObject()) + return false; + + decl = parser_vars->m_named_decl; + value = parser_vars->m_llvm_value; + offset = jit_vars->m_offset; + name = member_sp->GetName(); + + return true; +} + +bool +ClangExpressionDeclMap::GetFunctionInfo +( + const NamedDecl *decl, + uint64_t &ptr +) +{ + ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + + if (!entity) + return false; + + // We know m_parser_vars is valid since we searched for the variable by + // its NamedDecl + + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); + + return true; +} + +static void +FindCodeSymbolInContext +( + const ConstString &name, + SymbolContext &sym_ctx, + uint32_t name_type_mask, + SymbolContextList &sc_list +) +{ + sc_list.Clear(); + SymbolContextList temp_sc_list; + if (sym_ctx.module_sp) + sym_ctx.module_sp->FindFunctions(name, + NULL, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + if (temp_sc_list.GetSize() == 0) + { + if (sym_ctx.target_sp) + sym_ctx.target_sp->GetImages().FindFunctions(name, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + } + + SymbolContextList internal_symbol_sc_list; + unsigned temp_sc_list_size = temp_sc_list.GetSize(); + for (unsigned i = 0; i < temp_sc_list_size; i++) + { + SymbolContext sc; + temp_sc_list.GetContextAtIndex(i, sc); + if (sc.function) + { + sc_list.Append(sc); + } + else if (sc.symbol) + { + if (sc.symbol->IsExternal()) + { + sc_list.Append(sc); + } + else + { + internal_symbol_sc_list.Append(sc); + } + } + } + + // If we had internal symbols and we didn't find any external symbols or + // functions in debug info, then fallback to the internal symbols + if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize()) + { + sc_list = internal_symbol_sc_list; + } +} + +bool +ClangExpressionDeclMap::GetFunctionAddress +( + const ConstString &name, + uint64_t &func_addr +) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + // Back out in all cases where we're not fully initialized + if (target == NULL) + return false; + if (!m_parser_vars->m_sym_ctx.target_sp) + return false; + + SymbolContextList sc_list; + + FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); + + uint32_t sc_list_size = sc_list.GetSize(); + + if (sc_list_size == 0) + { + SymbolContext &sc = m_parser_vars->m_sym_ctx; + if (sc.comp_unit) + { + LanguageType lang_type = sc.comp_unit->GetLanguage(); + if (Language::LanguageIsCPlusPlus(lang_type) && + CPlusPlusLanguage::IsCPPMangledName(name.AsCString())) + { + // 1. Demangle the name + Mangled mangled(name, true); + ConstString demangled = mangled.GetDemangledName(lang_type); + + if (demangled) + { + FindCodeSymbolInContext( + demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list); + sc_list_size = sc_list.GetSize(); + } + } + } + } + + if (sc_list_size == 0) + { + // We occasionally get debug information in which a const function is reported + // as non-const, so the mangled name is wrong. This is a hack to compensate. + + if (!strncmp(name.GetCString(), "_ZN", 3) && + strncmp(name.GetCString(), "_ZNK", 4)) + { + std::string fixed_scratch("_ZNK"); + fixed_scratch.append(name.GetCString() + 3); + ConstString fixed_name(fixed_scratch.c_str()); + + if (log) + log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString()); + + FindCodeSymbolInContext( + fixed_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); + sc_list_size = sc_list.GetSize(); + } + } + + lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i=0; iGetAddressRange().GetBaseAddress(); + if (func_so_addr.IsValid()) + { + callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false); + } + } + else if (sym_ctx.symbol) + { + if (sym_ctx.symbol->IsExternal()) + callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); + else + { + if (intern_callable_load_addr == LLDB_INVALID_ADDRESS) + intern_callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); + } + } + + if (callable_load_addr != LLDB_INVALID_ADDRESS) + { + func_addr = callable_load_addr; + return true; + } + } + + // See if we found an internal symbol + if (intern_callable_load_addr != LLDB_INVALID_ADDRESS) + { + func_addr = intern_callable_load_addr; + return true; + } + + return false; +} + +addr_t +ClangExpressionDeclMap::GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + lldb_private::Module *module) +{ + SymbolContextList sc_list; + + if (module) + module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); + + const uint32_t num_matches = sc_list.GetSize(); + addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i=0; iGetAddress(); + + if (!sym_address.IsValid()) + continue; + + switch (sym_ctx.symbol->GetType()) + { + case eSymbolTypeCode: + case eSymbolTypeTrampoline: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target); + break; + + case eSymbolTypeResolver: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); + break; + + case eSymbolTypeReExported: + { + ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); + if (reexport_name) + { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) + { + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) + { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + } + } + symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); + } + } + break; + + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + symbol_load_addr = sym_address.GetLoadAddress (&target); + break; + } + } + + if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) + { + ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); + + if (runtime) + { + symbol_load_addr = runtime->LookupRuntimeSymbol(name); + } + } + + return symbol_load_addr; +} + +addr_t +ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type) +{ + assert (m_parser_vars.get()); + + if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) + return false; + + return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type); +} + +const Symbol * +ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, + const ConstString &name, + lldb_private::Module *module) +{ + SymbolContextList sc_list; + + if (module) + module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + + const uint32_t matches = sc_list.GetSize(); + for (uint32_t i=0; iGetAddress(); + + if (sym_address.IsValid()) + { + switch (symbol->GetType()) + { + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeAbsolute: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + if (symbol->GetDemangledNameIsSynthesized()) + { + // If the demangled name was synthesized, then don't use it + // for expressions. Only let the symbol match if the mangled + // named matches for these symbols. + if (symbol->GetMangled().GetMangledName() != name) + break; + } + return symbol; + + case eSymbolTypeReExported: + { + ConstString reexport_name = symbol->GetReExportedSymbolName(); + if (reexport_name) + { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) + { + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) + { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + } + } + // Don't allow us to try and resolve a re-exported symbol if it is the same + // as the current symbol + if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get()) + return NULL; + + return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get()); + } + } + break; + + case eSymbolTypeCode: // We already lookup functions elsewhere + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeTrampoline: + case eSymbolTypeInvalid: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeResolver: + break; + } + } + } + } + + return NULL; +} + +lldb::VariableSP +ClangExpressionDeclMap::FindGlobalVariable +( + Target &target, + ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type +) +{ + VariableList vars; + + if (module && namespace_decl) + module->FindGlobalVariables (name, namespace_decl, true, -1, vars); + else + target.GetImages().FindGlobalVariables(name, true, -1, vars); + + if (vars.GetSize()) + { + if (type) + { + for (size_t i = 0; i < vars.GetSize(); ++i) + { + VariableSP var_sp = vars.GetVariableAtIndex(i); + + if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetFullCompilerType ())) + return var_sp; + } + } + else + { + return vars.GetVariableAtIndex(0); + } + } + + return VariableSP(); +} + +// Interface for ClangASTSource + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) +{ + assert (m_ast_context); + + ClangASTMetrics::RegisterVisibleQuery(); + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (GetImportInProgress()) + { + if (log && log->GetVerbose()) + log->Printf("Ignoring a query during an import"); + return; + } + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (!context.m_decl_context) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString()); + else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName()); + } + + if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", + current_id, static_cast(namespace_map.get()), + (int)namespace_map->size()); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e; + ++i) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, + i->first, + i->second, + current_id); + } + } + else if (isa(context.m_decl_context)) + { + CompilerDeclContext namespace_decl; + + if (log) + log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id); + + FindExternalVisibleDecls(context, + lldb::ModuleSP(), + namespace_decl, + current_id); + } + + if (!context.m_found.variable) + ClangASTSource::FindExternalVisibleDecls(context); +} + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, + unsigned int current_id) +{ + assert (m_ast_context); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SymbolContextList sc_list; + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + const char *name_unique_cstr = name.GetCString(); + + if (name_unique_cstr == NULL) + return; + + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + + // Only look for functions by name out in our symbols if the function + // doesn't start with our phony prefix of '$' + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext sym_ctx; + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + if (name_unique_cstr[0] == '$' && !namespace_decl) + { + static ConstString g_lldb_class_name ("$__lldb_class"); + + if (name == g_lldb_class_name) + { + // Clang is looking for the type of "this" + + if (frame == NULL) + return; + + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + return; + + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + + if (!function_decl_ctx) + return; + + clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); + + if (method_decl) + { + clang::CXXRecordDecl *class_decl = method_decl->getParent(); + + QualType class_qual_type(class_decl->getTypeForDecl(), 0); + + TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&class_decl->getASTContext())); + + if (log) + { + ASTDumper ast_dumper(class_qual_type); + log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); + } + + AddThisType(context, class_user_type, current_id); + + if (method_decl->isInstance()) + { + // self is a pointer to the object + + QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); + + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + } + else + { + // This branch will get hit if we are executing code in the context of a function that + // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a + // method of the class. In that case, just look up the "this" variable in the current + // scope and use its type. + // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer + // for C++ so it hasn't actually been tested. + + VariableList *vars = frame->GetVariableList(false); + + lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); + + if (this_var && + this_var->IsInScope(frame) && + this_var->LocationIsValidForFrame (frame)) + { + Type *this_type = this_var->GetType(); + + if (!this_type) + return; + + TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType(); + + if (pointee_type.IsValid()) + { + if (log) + { + ASTDumper ast_dumper(pointee_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); + } + + AddThisType(context, pointee_type, current_id); + TypeFromUser this_user_type(this_type->GetFullCompilerType ()); + m_struct_vars->m_object_pointer_type = this_user_type; + return; + } + } + } + + return; + } + + static ConstString g_lldb_objc_class_name ("$__lldb_objc_class"); + if (name == g_lldb_objc_class_name) + { + // Clang is looking for the type of "*self" + + if (!frame) + return; + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + return; + + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + + if (!function_decl_ctx) + return; + + clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + + if (method_decl) + { + ObjCInterfaceDecl* self_interface = method_decl->getClassInterface(); + + if (!self_interface) + return; + + const clang::Type *interface_type = self_interface->getTypeForDecl(); + + if (!interface_type) + return; // This is unlikely, but we have seen crashes where this occurred + + TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + if (log) + { + ASTDumper ast_dumper(interface_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); + } + + AddOneType(context, class_user_type, current_id); + + if (method_decl->isInstanceMethod()) + { + // self is a pointer to the object + + QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); + + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + else + { + // self is a Class pointer + QualType class_type = method_decl->getASTContext().getObjCClassType(); + + TypeFromUser self_user_type(class_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + + return; + } + else + { + // This branch will get hit if we are executing code in the context of a function that + // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a + // method of the class. In that case, just look up the "self" variable in the current + // scope and use its type. + + VariableList *vars = frame->GetVariableList(false); + + lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + + if (self_var && + self_var->IsInScope(frame) && + self_var->LocationIsValidForFrame (frame)) + { + Type *self_type = self_var->GetType(); + + if (!self_type) + return; + + CompilerType self_clang_type = self_type->GetFullCompilerType (); + + if (ClangASTContext::IsObjCClassType(self_clang_type)) + { + return; + } + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) + { + self_clang_type = self_clang_type.GetPointeeType(); + + if (!self_clang_type) + return; + + if (log) + { + ASTDumper ast_dumper(self_type->GetFullCompilerType ()); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); + } + + TypeFromUser class_user_type (self_clang_type); + + AddOneType(context, class_user_type, current_id); + + TypeFromUser self_user_type(self_type->GetFullCompilerType ()); + + m_struct_vars->m_object_pointer_type = self_user_type; + return; + } + } + } + + return; + } + + // any other $__lldb names should be weeded out now + if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + return; + + do + { + if (!target) + break; + + ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext(); + + if (!scratch_clang_ast_context) + break; + + ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + + if (!scratch_ast_context) + break; + + TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name); + + if (!ptype_type_decl) + break; + + Decl *parser_ptype_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl); + + if (!parser_ptype_decl) + break; + + TypeDecl *parser_ptype_type_decl = dyn_cast(parser_ptype_decl); + + if (!parser_ptype_type_decl) + break; + + if (log) + log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString()); + + context.AddNamedDecl(parser_ptype_type_decl); + } while (0); + + ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); + + if (pvar_sp) + { + AddOneVariable(context, pvar_sp, current_id); + return; + } + + const char *reg_name(&name.GetCString()[1]); + + if (m_parser_vars->m_exe_ctx.GetRegisterContext()) + { + const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name)); + + if (reg_info) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name); + + AddOneRegister(context, reg_info, current_id); + } + } + } + else + { + ValueObjectSP valobj; + VariableSP var; + + if (frame && !namespace_decl) + { + CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + + if (compiler_decl_context) + { + // Make sure that the variables are parsed so that we have the declarations + VariableListSP vars = frame->GetInScopeVariableList(true); + for (size_t i = 0; i < vars->GetSize(); i++) + vars->GetVariableAtIndex(i)->GetDecl(); + + // Search for declarations matching the name + std::vector found_decls = compiler_decl_context.FindDeclByName(name); + + bool variable_found = false; + for (CompilerDecl decl : found_decls) + { + var = decl.GetAsVariable(); + if (var) + { + variable_found = true; + valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + } + } + if (variable_found) + return; + } + } + if (target) + { + var = FindGlobalVariable (*target, + module_sp, + name, + &namespace_decl, + NULL); + + if (var) + { + valobj = ValueObjectVariable::Create(target, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; + } + } + + std::vector decls_from_modules; + + if (target) + { + if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) + { + decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); + } + } + + if (!context.m_found.variable) + { + const bool include_inlines = false; + const bool append = false; + + if (namespace_decl && module_sp) + { + const bool include_symbols = false; + + module_sp->FindFunctions(name, + &namespace_decl, + eFunctionNameTypeBase, + include_symbols, + include_inlines, + append, + sc_list); + } + else if (target && !namespace_decl) + { + const bool include_symbols = true; + + // TODO Fix FindFunctions so that it doesn't return + // instance methods for eFunctionNameTypeBase. + + target->GetImages().FindFunctions(name, + eFunctionNameTypeFull, + include_symbols, + include_inlines, + append, + sc_list); + } + + // If we found more than one function, see if we can use the + // frame's decl context to remove functions that are shadowed + // by other functions which match in type but are nearer in scope. + // + // AddOneFunction will not add a function whose type has already been + // added, so if there's another function in the list with a matching + // type, check to see if their decl context is a parent of the current + // frame's or was imported via a and using statement, and pick the + // best match according to lookup rules. + if (sc_list.GetSize() > 1) + { + // Collect some info about our frame's context. + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext frame_sym_ctx; + if (frame != nullptr) + frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + CompilerDeclContext frame_decl_context = frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + + // We can't do this without a compiler decl context for our frame. + if (frame_decl_context) + { + clang::DeclContext *frame_decl_ctx = (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); + ClangASTContext *ast = llvm::dyn_cast_or_null(frame_decl_context.GetTypeSystem()); + + // Structure to hold the info needed when comparing function + // declarations. + struct FuncDeclInfo + { + ConstString m_name; + CompilerType m_copied_type; + uint32_t m_decl_lvl; + SymbolContext m_sym_ctx; + }; + + // First, symplify things by looping through the symbol contexts + // to remove unwanted functions and separate out the functions we + // want to compare and prune into a separate list. + // Cache the info needed about the function declarations in a + // vector for efficiency. + SymbolContextList sc_sym_list; + uint32_t num_indices = sc_list.GetSize(); + std::vector fdi_cache; + fdi_cache.reserve(num_indices); + for (uint32_t index = 0; index < num_indices; ++index) + { + FuncDeclInfo fdi; + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + // We don't know enough about symbols to compare them, + // but we should keep them in the list. + Function *function = sym_ctx.function; + if (!function) + { + sc_sym_list.Append(sym_ctx); + continue; + } + // Filter out functions without declaration contexts, as well as + // class/instance methods, since they'll be skipped in the + // code that follows anyway. + CompilerDeclContext func_decl_context = function->GetDeclContext(); + if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + // We can only prune functions for which we can copy the type. + CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); + CompilerType copied_func_type = GuardedCopyType(func_clang_type); + if (!copied_func_type) + { + sc_sym_list.Append(sym_ctx); + continue; + } + + fdi.m_sym_ctx = sym_ctx; + fdi.m_name = function->GetName(); + fdi.m_copied_type = copied_func_type; + fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; + if (fdi.m_copied_type && func_decl_context) + { + // Call CountDeclLevels to get the number of parent scopes we + // have to look through before we find the function declaration. + // When comparing functions of the same type, the one with a + // lower count will be closer to us in the lookup scope and + // shadows the other. + clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); + fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, + func_decl_ctx, + &fdi.m_name, + &fdi.m_copied_type); + } + fdi_cache.emplace_back(fdi); + } + + // Loop through the functions in our cache looking for matching types, + // then compare their scope levels to see which is closer. + std::multimap matches; + for (const FuncDeclInfo &fdi : fdi_cache) + { + const CompilerType t = fdi.m_copied_type; + auto q = matches.find(t); + if (q != matches.end()) + { + if (q->second->m_decl_lvl > fdi.m_decl_lvl) + // This function is closer; remove the old set. + matches.erase(t); + else if (q->second->m_decl_lvl < fdi.m_decl_lvl) + // The functions in our set are closer - skip this one. + continue; + } + matches.insert(std::make_pair(t, &fdi)); + } + + // Loop through our matches and add their symbol contexts to our list. + SymbolContextList sc_func_list; + for (const auto &q : matches) + sc_func_list.Append(q.second->m_sym_ctx); + + // Rejoin the lists with the functions in front. + sc_list = sc_func_list; + sc_list.Append(sc_sym_list); + } + } + + if (sc_list.GetSize()) + { + Symbol *extern_symbol = NULL; + Symbol *non_extern_symbol = NULL; + + for (uint32_t index = 0, num_indices = sc_list.GetSize(); + index < num_indices; + ++index) + { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + if (sym_ctx.function) + { + CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); + + if (!decl_ctx) + continue; + + // Filter out class/instance methods. + if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + + AddOneFunction(context, sym_ctx.function, NULL, current_id); + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } + else if (sym_ctx.symbol) + { + if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) + { + sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); + if (sym_ctx.symbol == NULL) + continue; + } + + if (sym_ctx.symbol->IsExternal()) + extern_symbol = sym_ctx.symbol; + else + non_extern_symbol = sym_ctx.symbol; + } + } + + if (!context.m_found.function_with_type_info) + { + for (clang::NamedDecl *decl : decls_from_modules) + { + if (llvm::isa(decl)) + { + clang::NamedDecl *copied_decl = llvm::cast(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); + context.AddNamedDecl(copied_decl); + context.m_found.function_with_type_info = true; + } + } + } + + if (!context.m_found.function_with_type_info) + { + if (extern_symbol) + { + AddOneFunction (context, NULL, extern_symbol, current_id); + context.m_found.function = true; + } + else if (non_extern_symbol) + { + AddOneFunction (context, NULL, non_extern_symbol, current_id); + context.m_found.function = true; + } + } + } + + if (!context.m_found.function_with_type_info) + { + // Try the modules next. + + do + { + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa(decl_from_modules)) + { + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_function_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules", + current_id); + + break; + } + + if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) + { + DeclGroupRef decl_group_ref(copied_function_decl); + m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); + } + + context.AddNamedDecl(copied_function_decl); + + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } + else if (llvm::isa(decl_from_modules)) + { + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null(copied_decl) : nullptr; + + if (!copied_var_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_var_decl); + + context.m_found.variable = true; + } + } + } while (0); + } + + if (target && !context.m_found.variable && !namespace_decl) + { + // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic + // data symbol, and -- if it is found -- treat it as a variable. + + const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); + + if (data_symbol) + { + std::string warning("got name from symbols: "); + warning.append(name.AsCString()); + const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); + AddOneGenericVariable(context, *data_symbol, current_id); + context.m_found.variable = true; + } + } + } + } +} + +//static opaque_compiler_type_t +//MaybePromoteToBlockPointerType +//( +// ASTContext *ast_context, +// opaque_compiler_type_t candidate_type +//) +//{ +// if (!candidate_type) +// return candidate_type; +// +// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); +// +// const PointerType *candidate_pointer_type = dyn_cast(candidate_qual_type); +// +// if (!candidate_pointer_type) +// return candidate_type; +// +// QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); +// +// const RecordType *pointee_record_type = dyn_cast(pointee_qual_type); +// +// if (!pointee_record_type) +// return candidate_type; +// +// RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); +// +// if (!pointee_record_decl->isRecord()) +// return candidate_type; +// +// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) +// return candidate_type; +// +// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); +// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type); +// +// return block_pointer_type.getAsOpaquePtr(); +//} + +bool +ClangExpressionDeclMap::GetVariableValue (VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *user_type, + TypeFromParser *parser_type) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Type *var_type = var->GetType(); + + if (!var_type) + { + if (log) + log->PutCString("Skipped a definition because it has no type"); + return false; + } + + CompilerType var_clang_type = var_type->GetFullCompilerType (); + + if (!var_clang_type) + { + if (log) + log->PutCString("Skipped a definition because it has no Clang type"); + return false; + } + + ClangASTContext *clang_ast = llvm::dyn_cast_or_null(var_type->GetForwardCompilerType().GetTypeSystem()); + + if (!clang_ast) + { + if (log) + log->PutCString("Skipped a definition because it has no Clang AST"); + return false; + } + + + ASTContext *ast = clang_ast->getASTContext(); + + if (!ast) + { + if (log) + log->PutCString("There is no AST context for the current execution context"); + return false; + } + //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); + + DWARFExpression &var_location_expr = var->LocationExpression(); + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + Error err; + + if (var->GetLocationIsConstantValueData()) + { + DataExtractor const_value_extractor; + + if (var_location_expr.GetExpressionData(const_value_extractor)) + { + var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); + var_location.SetValueType(Value::eValueTypeHostAddress); + } + else + { + if (log) + log->Printf("Error evaluating constant variable: %s", err.AsCString()); + return false; + } + } + + CompilerType type_to_use = GuardedCopyType(var_clang_type); + + if (!type_to_use) + { + if (log) + log->Printf("Couldn't copy a variable's type into the parser's AST context"); + + return false; + } + + if (parser_type) + *parser_type = TypeFromParser(type_to_use); + + if (var_location.GetContextType() == Value::eContextTypeInvalid) + var_location.SetCompilerType(type_to_use); + + if (var_location.GetValueType() == Value::eValueTypeFileAddress) + { + SymbolContext var_sc; + var->CalculateSymbolContext(&var_sc); + + if (!var_sc.module_sp) + return false; + + Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList()); + + lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + + if (load_addr != LLDB_INVALID_ADDRESS) + { + var_location.GetScalar() = load_addr; + var_location.SetValueType(Value::eValueTypeLoadAddress); + } + } + + if (user_type) + *user_type = TypeFromUser(var_clang_type); + + return true; +} + +void +ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + TypeFromUser ut; + TypeFromParser pt; + Value var_location; + + if (!GetVariableValue (var, var_location, &ut, &pt)) + return; + + clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); + + if (parser_opaque_type.isNull()) + return; + + if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) + { + if (const TagType *tag_type = dyn_cast(parser_type)) + CompleteType(tag_type->getDecl()); + if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast(parser_type)) + CompleteType(objc_object_ptr_type->getInterfaceDecl()); + } + + + bool is_reference = pt.IsReferenceType(); + + NamedDecl *var_decl = NULL; + if (is_reference) + var_decl = context.AddVarDecl(pt); + else + var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); + m_found_entities.AddNewlyConstructedVariable(entity); + + assert (entity); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = pt; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value = var_location; + parser_vars->m_lldb_var = var; + + if (is_reference) + entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + + if (log) + { + ASTDumper orig_dumper(ut.GetOpaqueQualType()); + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + ExpressionVariableSP &pvar_sp, + unsigned int current_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + TypeFromUser user_type (llvm::cast(pvar_sp.get())->GetTypeFromUser()); + + TypeFromParser parser_type (GuardedCopyType(user_type)); + + if (!parser_type.GetOpaqueQualType()) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString()); + return; + } + + NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); + + llvm::cast(pvar_sp.get())->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(pvar_sp.get())->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + + if (log) + { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id) +{ + assert(m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + if (target == NULL) + return; + + ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); + + TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); + TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); + NamedDecl *var_decl = context.AddVarDecl(parser_type); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), + entity_name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + const Address symbol_address = symbol.GetAddress(); + lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); + + //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_sym = &symbol; + + if (log) + { + ASTDumper ast_dumper(var_decl); + + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString()); + } +} + +bool +ClangExpressionDeclMap::ResolveUnknownTypes() +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + + for (size_t index = 0, num_entities = m_found_entities.GetSize(); + index < num_entities; + ++index) + { + ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(entity.get())->GetParserVars(GetParserID()); + + if (entity->m_flags & ClangExpressionVariable::EVUnknownType) + { + const NamedDecl *named_decl = parser_vars->m_named_decl; + const VarDecl *var_decl = dyn_cast(named_decl); + + if (!var_decl) + { + if (log) + log->Printf("Entity of unknown type does not have a VarDecl"); + return false; + } + + if (log) + { + ASTDumper ast_dumper(const_cast(var_decl)); + log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString()); + } + + QualType var_type = var_decl->getType(); + TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); + + lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr()); + + if (!copied_type) + { + if (log) + log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable"); + + return (bool) lldb::ExpressionVariableSP(); + } + + TypeFromUser user_type(copied_type, scratch_ast_context); + +// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_parser_type = parser_type; + + entity->SetCompilerType(user_type); + + entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); + } + } + + return true; +} + +void +ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context, + reg_info->encoding, + reg_info->byte_size * 8); + + if (!clang_type) + { + if (log) + log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str()); + return; + } + + TypeFromParser parser_clang_type (clang_type); + + NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); + + ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName (ConstString (decl_name.c_str())); + entity->SetRegisterInfo (reg_info); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_clang_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + entity->m_flags |= ClangExpressionVariable::EVBareRegister; + + if (log) + { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, + Function* function, + Symbol* symbol, + unsigned int current_id) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + NamedDecl *function_decl = NULL; + Address fun_address; + CompilerType function_clang_type; + + bool is_indirect_function = false; + + if (function) + { + Type *function_type = function->GetType(); + + if (!function_type) + { + if (log) + log->PutCString(" Skipped a function because it has no type"); + return; + } + + function_clang_type = function_type->GetFullCompilerType (); + + if (!function_clang_type) + { + if (log) + log->PutCString(" Skipped a function because it has no Clang type"); + return; + } + + fun_address = function->GetAddressRange().GetBaseAddress(); + + CompilerType copied_function_type = GuardedCopyType(function_clang_type); + if (copied_function_type) + { + function_decl = context.AddFunDecl(copied_function_type); + + if (!function_decl) + { + if (log) + { + log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", + function_type->GetName().GetCString(), + function_type->GetID()); + } + + return; + } + } + else + { + // We failed to copy the type we found + if (log) + { + log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt", + function_type->GetName().GetCString(), + function_type->GetID()); + } + + return; + } + } + else if (symbol) + { + fun_address = symbol->GetAddress(); + function_decl = context.AddGenericFunDecl(); + is_indirect_function = symbol->IsIndirect(); + } + else + { + if (log) + log->PutCString(" AddOneFunction called with no function and no symbol"); + return; + } + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); + + ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName(ConstString(decl_name.c_str())); + entity->SetCompilerType (function_clang_type); + entity->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + if (load_addr != LLDB_INVALID_ADDRESS) + { + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + parser_vars->m_lldb_value.GetScalar() = load_addr; + } + else + { + // We have to try finding a file address. + + lldb::addr_t file_addr = fun_address.GetFileAddress(); + + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); + parser_vars->m_lldb_value.GetScalar() = file_addr; + } + + + parser_vars->m_named_decl = function_decl; + parser_vars->m_llvm_value = NULL; + + if (log) + { + ASTDumper ast_dumper(function_decl); + + StreamString ss; + + fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); + + log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", + current_id, + (function ? "specific" : "generic"), + decl_name.c_str(), + ss.GetData(), + ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddThisType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) +{ + CompilerType copied_clang_type = GuardedCopyType(ut); + + if (!copied_clang_type) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type"); + + return; + } + + if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ()) + { + CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); + CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); + + CompilerType method_type = ClangASTContext::CreateFunctionType (m_ast_context, + void_clang_type, + &void_ptr_clang_type, + 1, + false, + copied_clang_type.GetTypeQualifiers()); + + const bool is_virtual = false; + const bool is_static = false; + const bool is_inline = false; + const bool is_explicit = false; + const bool is_attr_used = true; + const bool is_artificial = false; + + ClangASTContext::GetASTContext(m_ast_context)-> + AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), + "$__lldb_expr", + method_type, + lldb::eAccessPublic, + is_virtual, + is_static, + is_inline, + is_explicit, + is_attr_used, + is_artificial); + } + + if (!copied_clang_type.IsValid()) + return; + + TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType())); + + if (!type_source_info) + return; + + // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries. + // Using a typedef makes this much more robust. + + TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context, + m_ast_context->getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + context.m_decl_name.getAsIdentifierInfo(), + type_source_info); + + + if (!typedef_decl) + return; + + context.AddNamedDecl(typedef_decl); + + return; +} + +void +ClangExpressionDeclMap::AddOneType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) +{ + CompilerType copied_clang_type = GuardedCopyType(ut); + + if (!copied_clang_type) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + + return; + } + + context.AddTypeDecl(copied_clang_type); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h new file mode 100644 index 000000000000..b3f890c7acc7 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -0,0 +1,714 @@ +//===-- ClangExpressionDeclMap.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_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include +#include + +// C++ Includes +#include + +#include "ClangExpressionVariable.h" +#include "ClangASTSource.h" + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression. The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name. But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap : + public ClangASTSource +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] delegate + /// If non-NULL, use this delegate to report result values. This + /// allows the client ClangUserExpression to report a result. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap (bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap() override; + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool + WillParse (ExecutionContext &exe_ctx, + Materializer *materializer); + + void + InstallCodeGenerator (clang::ASTConsumer *code_gen); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void + DidParse (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddPersistentVariable (const clang::NamedDecl *decl, + const ConstString &name, + TypeFromParser type, + bool is_result, + bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddValueToStruct (const clang::NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + lldb::offset_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + DoStructLayout (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructInfo (uint32_t &num_elements, + size_t &size, + lldb::offset_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructElement (const clang::NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionInfo (const clang::NamedDecl *decl, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a function given nothing + /// but its name. Some functions are needed but didn't get Decls made + /// during parsing -- specifically, sel_registerName is never called + /// in the generated IR but we need to call it nonetheless. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the address could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionAddress (const ConstString &name, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t + GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + Module *module = NULL); + + lldb::addr_t + GetSymbolAddress (const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo + { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : + byte_order(lldb::eByteOrderInvalid), + address_byte_size(0) + { + } + + bool IsValid() + { + return (byte_order != lldb::eByteOrderInvalid && + address_byte_size != 0); + } + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls(NameSearchContext &context) override; + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @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. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); +private: + ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. + ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. + Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to ClangUserExpression. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : + m_decl_map(decl_map) + { + } + + Target * + GetTarget() + { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; + } + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. + bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. + clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN (ParserVars); + }; + + std::unique_ptr m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars() + { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars() + { + m_parser_vars.reset(); + } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() : + m_struct_alignment(0), + m_struct_size(0), + m_struct_laid_out(false), + m_result_name(), + m_object_pointer_type(NULL, NULL) + { + } + + lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). + ConstString m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists + }; + + std::unique_ptr m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void + EnableStructVars() + { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void + DisableStructVars() + { + m_struct_vars.reset(); + } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t + GetParserID() + { + return (uint64_t)this; + } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //------------------------------------------------------------------ + const Symbol * + FindGlobalDataSymbol (Target &target, + const ConstString &name, + Module *module = NULL); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP + FindGlobalVariable (Target &target, + lldb::ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool + GetVariableValue (lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::VariableSP var, + lldb::ValueObjectSP valobj, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::ExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void + AddOneGenericVariable (NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void + AddOneFunction (NameSearchContext &context, + Function *fun, + Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void + AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void + AddOneType (NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Generate a Decl for "*this" and add a member function declaration + /// to it for the expression, then report it. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type for *this. + //------------------------------------------------------------------ + void + AddThisType(NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h new file mode 100644 index 000000000000..bb620def691f --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -0,0 +1,79 @@ +//===-- ClangExpression.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_ClangExpression_h_ +#define liblldb_ClangExpression_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ExpressionTypeSystemHelper.h" + +namespace lldb_private { + +class RecordingMemoryManager; + +//---------------------------------------------------------------------- +// ClangExpressionHelper +//---------------------------------------------------------------------- +class ClangExpressionHelper : public ExpressionTypeSystemHelper +{ +public: + static bool classof(const ExpressionTypeSystemHelper *ts) + { + return ts->getKind() == eKindClangHelper; + } + + ClangExpressionHelper () : + ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) + { + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~ClangExpressionHelper () + { + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + virtual ClangExpressionDeclMap * + DeclMap () = 0; + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + virtual clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough) = 0; + + +protected: + +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp new file mode 100644 index 000000000000..72c33fec8105 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -0,0 +1,657 @@ +//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetSelect.h" + +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" + +// Project includes +#include "ClangExpressionParser.h" + +#include "ClangASTSource.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionDeclMap.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" +#include "IRForTarget.h" + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/File.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace clang; +using namespace llvm; +using namespace lldb_private; + +//===----------------------------------------------------------------------===// +// Utility Methods for Clang +//===----------------------------------------------------------------------===// + +std::string GetBuiltinIncludePath(const char *Argv0) { + SmallString<128> P(llvm::sys::fs::getMainExecutable( + Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); + + if (!P.empty()) { + llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang + llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin + + // Get foo/lib/clang//include + llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, + "include"); + } + + return P.str(); +} + +class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks +{ + ClangModulesDeclVendor &m_decl_vendor; + ClangPersistentVariables &m_persistent_vars; + StreamString m_error_stream; + bool m_has_errors = false; + +public: + LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, + ClangPersistentVariables &persistent_vars) : + m_decl_vendor(decl_vendor), + m_persistent_vars(persistent_vars) + { + } + + void + moduleImport(SourceLocation import_location, + clang::ModuleIdPath path, + const clang::Module * /*null*/) override + { + std::vector string_path; + + for (const std::pair &component : path) + { + string_path.push_back(ConstString(component.first->getName())); + } + + StreamString error_stream; + + ClangModulesDeclVendor::ModuleVector exported_modules; + + if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) + { + m_has_errors = true; + } + + for (ClangModulesDeclVendor::ModuleID module : exported_modules) + { + m_persistent_vars.AddHandLoadedClangModule(module); + } + } + + bool hasErrors() + { + return m_has_errors; + } + + const std::string &getErrorString() + { + return m_error_stream.GetString(); + } +}; + +//===----------------------------------------------------------------------===// +// Implementation of ClangExpressionParser +//===----------------------------------------------------------------------===// + +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) +{ + // 1. Create a new compiler instance. + m_compiler.reset(new CompilerInstance()); + + // 2. Install the target. + + lldb::TargetSP target_sp; + if (exe_scope) + target_sp = exe_scope->CalculateTarget(); + + // TODO: figure out what to really do when we don't have a valid target. + // Sometimes this will be ok to just use the host target triple (when we + // evaluate say "2+3", but other expressions like breakpoint conditions + // and other things that _are_ target specific really shouldn't just be + // using the host triple. This needs to be fixed in a better way. + if (target_sp && target_sp->GetArchitecture().IsValid()) + { + std::string triple = target_sp->GetArchitecture().GetTriple().str(); + m_compiler->getTargetOpts().Triple = triple; + } + else + { + m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); + } + + if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || + target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) + { + m_compiler->getTargetOpts().Features.push_back("+sse"); + m_compiler->getTargetOpts().Features.push_back("+sse2"); + } + + // Any arm32 iOS environment, but not on arm64 + if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && + m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && + m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) + { + m_compiler->getTargetOpts().ABI = "apcs-gnu"; + } + + m_compiler->createDiagnostics(); + + // Create the target instance. + m_compiler->setTarget(TargetInfo::CreateTargetInfo( + m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); + + assert (m_compiler->hasTarget()); + + // 3. Set options. + + lldb::LanguageType language = expr.Language(); + + switch (language) + { + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC89: + case lldb::eLanguageTypeC99: + case lldb::eLanguageTypeC11: + // FIXME: the following language option is a temporary workaround, + // to "ask for C, get C++." + // For now, the expression parser must use C++ anytime the + // language is a C family language, because the expression parser + // uses features of C++ to capture values. + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeObjC: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + // FIXME: the following language option is a temporary workaround, + // to "ask for ObjC, get ObjC++" (see comment above). + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeC_plus_plus_11: + case lldb::eLanguageTypeC_plus_plus_14: + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + // fall thru ... + 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; + break; + case lldb::eLanguageTypeObjC_plus_plus: + case lldb::eLanguageTypeUnknown: + default: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + m_compiler->getLangOpts().CPlusPlus = true; + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + break; + } + + m_compiler->getLangOpts().Bool = true; + m_compiler->getLangOpts().WChar = true; + m_compiler->getLangOpts().Blocks = true; + m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients + if (expr.DesiredResultType() == Expression::eResultTypeId) + m_compiler->getLangOpts().DebuggerCastResultToId = true; + + m_compiler->getLangOpts().CharIsSigned = + ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); + + // Spell checking is a nice feature, but it ends up completing a + // lot of types that we didn't strictly speaking need to complete. + // As a result, we spend a long time parsing and importing debug + // information. + m_compiler->getLangOpts().SpellChecking = false; + + lldb::ProcessSP process_sp; + if (exe_scope) + process_sp = exe_scope->CalculateProcess(); + + if (process_sp && m_compiler->getLangOpts().ObjC1) + { + if (process_sp->GetObjCLanguageRuntime()) + { + if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); + else + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); + + if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) + m_compiler->getLangOpts().DebuggerObjCLiteral = true; + } + } + + m_compiler->getLangOpts().ThreadsafeStatics = false; + m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access + m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name + + // Set CodeGen options + m_compiler->getCodeGenOpts().EmitDeclMetadata = true; + m_compiler->getCodeGenOpts().InstrumentFunctions = false; + m_compiler->getCodeGenOpts().DisableFPElim = true; + m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; + if (generate_debug_info) + m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); + else + m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); + + // Disable some warnings. + m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, + "unused-value", clang::diag::Severity::Ignored, SourceLocation()); + m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, + "odr", clang::diag::Severity::Ignored, SourceLocation()); + + // Inform the target of the language options + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + m_compiler->getTarget().adjust(m_compiler->getLangOpts()); + + // 4. Set up the diagnostic buffer for reporting errors + + m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + + // 5. Set up the source management objects inside the compiler + + clang::FileSystemOptions file_system_options; + m_file_manager.reset(new clang::FileManager(file_system_options)); + + if (!m_compiler->hasSourceManager()) + m_compiler->createSourceManager(*m_file_manager.get()); + + m_compiler->createFileManager(); + m_compiler->createPreprocessor(TU_Complete); + + if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) + { + ClangPersistentVariables *clang_persistent_vars = llvm::cast(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + std::unique_ptr pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); + m_pp_callbacks = static_cast(pp_callbacks.get()); + m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + } + + // 6. Most of this we get from the CompilerInstance, but we + // also want to give the context an ExternalASTSource. + m_selector_table.reset(new SelectorTable()); + m_builtin_context.reset(new Builtin::Context()); + + std::unique_ptr ast_context(new ASTContext(m_compiler->getLangOpts(), + m_compiler->getSourceManager(), + m_compiler->getPreprocessor().getIdentifierTable(), + *m_selector_table.get(), + *m_builtin_context.get())); + + ast_context->InitBuiltinTypes(m_compiler->getTarget()); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); + + if (decl_map) + { + llvm::IntrusiveRefCntPtr ast_source(decl_map->CreateProxy()); + decl_map->InstallASTContext(ast_context.get()); + 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()); + + std::string module_name("$__lldb_module"); + + m_llvm_context.reset(new LLVMContext()); + m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), + module_name, + m_compiler->getHeaderSearchOpts(), + m_compiler->getPreprocessorOpts(), + m_compiler->getCodeGenOpts(), + *m_llvm_context)); +} + +ClangExpressionParser::~ClangExpressionParser() +{ +} + +unsigned +ClangExpressionParser::Parse (Stream &stream) +{ + TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); + + diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); + + const char *expr_text = m_expr.Text(); + + clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); + bool created_main_file = false; + if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) + { + std::string temp_source_path; + + int temp_fd = -1; + llvm::SmallString result_path; + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); + temp_source_path = tmpdir_file_spec.GetPath(); + llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); + } + else + { + llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); + } + + if (temp_fd != -1) + { + lldb_private::File file (temp_fd, true); + const size_t expr_text_len = strlen(expr_text); + size_t bytes_written = expr_text_len; + if (file.Write(expr_text, bytes_written).Success()) + { + if (bytes_written == expr_text_len) + { + file.Close(); + SourceMgr.setMainFileID(SourceMgr.createFileID( + m_file_manager->getFile(result_path), + SourceLocation(), SrcMgr::C_User)); + created_main_file = true; + } + } + } + } + + if (!created_main_file) + { + std::unique_ptr memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); + SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); + } + + diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + + ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); + + if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) + decl_map->InstallCodeGenerator(m_code_generator.get()); + + if (ast_transformer) + { + ast_transformer->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); + } + else + { + m_code_generator->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); + } + + diag_buf->EndSourceFile(); + + TextDiagnosticBuffer::const_iterator diag_iterator; + + int num_errors = 0; + + if (m_pp_callbacks && m_pp_callbacks->hasErrors()) + { + num_errors++; + + stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + } + + for (diag_iterator = diag_buf->warn_begin(); + diag_iterator != diag_buf->warn_end(); + ++diag_iterator) + stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); + + for (diag_iterator = diag_buf->err_begin(); + diag_iterator != diag_buf->err_end(); + ++diag_iterator) + { + num_errors++; + stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); + } + + for (diag_iterator = diag_buf->note_begin(); + diag_iterator != diag_buf->note_end(); + ++diag_iterator) + stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); + + if (!num_errors) + { + if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) + { + stream.Printf("error: Couldn't infer the type of a variable\n"); + num_errors++; + } + } + + return num_errors; +} + +static bool FindFunctionInModule (ConstString &mangled_name, + llvm::Module *module, + const char *orig_name) +{ + for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); + fi != fe; + ++fi) + { + if (fi->getName().str().find(orig_name) != std::string::npos) + { + mangled_name.SetCString(fi->getName().str().c_str()); + return true; + } + } + + return false; +} + +Error +ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + ExecutionPolicy execution_policy) +{ + func_addr = LLDB_INVALID_ADDRESS; + func_end = LLDB_INVALID_ADDRESS; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Error err; + + std::unique_ptr llvm_module_ap (m_code_generator->ReleaseModule()); + + if (!llvm_module_ap.get()) + { + err.SetErrorToGenericError(); + err.SetErrorString("IR doesn't contain a module"); + return err; + } + + // Find the actual name of the function (it's often mangled somehow) + + ConstString function_name; + + if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) + { + err.SetErrorToGenericError(); + err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); + return err; + } + else + { + if (log) + log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); + } + + execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here + llvm_module_ap, // handed off here + function_name, + exe_ctx.GetTargetSP(), + m_compiler->getTargetOpts().Features)); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL + + if (decl_map) + { + Stream *error_stream = NULL; + Target *target = exe_ctx.GetTargetPtr(); + if (target) + error_stream = target->GetDebugger().GetErrorFile().get(); + + IRForTarget ir_for_target(decl_map, + m_expr.NeedsVariableResolution(), + *execution_unit_sp, + error_stream, + function_name.AsCString()); + + bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); + + Error interpret_error; + Process *process = exe_ctx.GetProcessPtr(); + + bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); + can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); + + + if (!ir_can_run) + { + err.SetErrorString("The expression could not be prepared to run in the target"); + return err; + } + + if (!can_interpret && execution_policy == eExecutionPolicyNever) + { + err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); + return err; + } + + if (!process && execution_policy == eExecutionPolicyAlways) + { + err.SetErrorString("Expression needed to run in the target, but the target can't be run"); + return err; + } + + if (execution_policy == eExecutionPolicyAlways || !can_interpret) + { + if (m_expr.NeedsValidation() && process) + { + if (!process->GetDynamicCheckers()) + { + DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); + + StreamString install_errors; + + if (!dynamic_checkers->Install(install_errors, exe_ctx)) + { + if (install_errors.GetString().empty()) + err.SetErrorString ("couldn't install checkers, unknown error"); + else + err.SetErrorString (install_errors.GetString().c_str()); + + return err; + } + + process->SetDynamicCheckers(dynamic_checkers); + + if (log) + log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); + } + + IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); + + if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) + { + err.SetErrorToGenericError(); + err.SetErrorString("Couldn't add dynamic checks to the expression"); + return err; + } + } + + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + } + } + else + { + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + } + + return err; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h new file mode 100644 index 000000000000..3c055380b839 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -0,0 +1,136 @@ +//===-- ClangExpressionParser.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_ClangExpressionParser_h_ +#define liblldb_ClangExpressionParser_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/ExpressionParser.h" + +#include +#include + +namespace lldb_private +{ + +class IRExecutionUnit; + +//---------------------------------------------------------------------- +/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" +/// @brief Encapsulates an instance of Clang that can parse expressions. +/// +/// ClangExpressionParser is responsible for preparing an instance of +/// ClangExpression for execution. ClangExpressionParser uses ClangExpression +/// as a glorified parameter list, performing the required parsing and +/// conversion to formats (DWARF bytecode, or JIT compiled machine code) +/// that can be executed. +//---------------------------------------------------------------------- +class ClangExpressionParser : public ExpressionParser +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] exe_scope, + /// If non-NULL, an execution context scope that can help to + /// correctly create an expression with a valid process for + /// optional tuning Objective-C runtime support. Can be NULL. + /// + /// @param[in] expr + /// The expression to be parsed. + //------------------------------------------------------------------ + ClangExpressionParser (ExecutionContextScope *exe_scope, + Expression &expr, + bool generate_debug_info); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionParser () override; + + //------------------------------------------------------------------ + /// Parse a single expression and convert it to IR using Clang. Don't + /// wrap the expression in anything at all. + /// + /// @param[in] stream + /// The stream to print errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + unsigned + Parse (Stream &stream) override; + + //------------------------------------------------------------------ + /// Ready an already-parsed expression for execution, possibly + /// evaluating it statically. + /// + /// @param[out] func_addr + /// The address to which the function has been written. + /// + /// @param[out] func_end + /// The end of the function's allocated memory region. (func_addr + /// and func_end do not delimit an allocated region; the allocated + /// region may begin before func_addr.) + /// + /// @param[in] execution_unit_sp + /// After parsing, ownership of the execution unit for + /// for the expression is handed to this shared pointer. + /// + /// @param[in] exe_ctx + /// The execution context to write the function into. + /// + /// @param[out] evaluated_statically + /// Set to true if the expression could be interpreted statically; + /// untouched otherwise. + /// + /// @param[out] const_result + /// If the result of the expression is constant, and the + /// expression has no side effects, this is set to the result of the + /// expression. + /// + /// @param[in] execution_policy + /// Determines whether the expression must be JIT-compiled, must be + /// evaluated statically, or whether this decision may be made + /// opportunistically. + /// + /// @return + /// An error code indicating the success or failure of the operation. + /// Test with Success(). + //------------------------------------------------------------------ + Error + PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; + +private: + std::unique_ptr m_llvm_context; ///< The LLVM context to generate IR into + std::unique_ptr m_file_manager; ///< The Clang file manager object used by the compiler + std::unique_ptr m_compiler; ///< The Clang compiler used to parse expressions into IR + std::unique_ptr m_builtin_context; ///< Context for Clang built-ins + std::unique_ptr m_selector_table; ///< Selector table for Objective-C methods + std::unique_ptr m_code_generator; ///< The Clang object that generates IR + + class LLDBPreprocessorCallbacks; + LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports + std::unique_ptr m_ast_context; +}; + +} + +#endif // liblldb_ClangExpressionParser_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp new file mode 100644 index 000000000000..908546b3ecdb --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp @@ -0,0 +1,76 @@ +//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionVariable.h" + +#include "clang/AST/ASTContext.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" + +using namespace lldb_private; +using namespace clang; + +const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable"; + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = EVNone; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); +} + +ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = flags; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name); +} + +ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = EVNone; + m_frozen_sp = valobj_sp; +} + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars() +{ + m_flags = EVNone; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); + SetName (name); + SetCompilerType (user_type); +} + +TypeFromUser +ClangExpressionVariable::GetTypeFromUser() +{ + TypeFromUser tfu (m_frozen_sp->GetCompilerType()); + return tfu; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h new file mode 100644 index 000000000000..a4596148f6c7 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -0,0 +1,265 @@ +//===-- ClangExpressionVariable.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_ClangExpressionVariable_h_ +#define liblldb_ClangExpressionVariable_h_ + +// C Includes +#include +#include +#include + +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/Support/Casting.h" + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TaggedASTType.h" + +namespace llvm { + class Value; +} + +namespace lldb_private { + +class ValueObjectConstResult; + +//---------------------------------------------------------------------- +/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @brief Encapsulates one variable for the expression parser. +/// +/// The expression parser uses variables in three different contexts: +/// +/// First, it stores persistent variables along with the process for use +/// in expressions. These persistent variables contain their own data +/// and are typed. +/// +/// Second, in an interpreted expression, it stores the local variables +/// for the expression along with the expression. These variables +/// contain their own data and are typed. +/// +/// Third, in a JIT-compiled expression, it stores the variables that +/// the expression needs to have materialized and dematerialized at each +/// execution. These do not contain their own data but are named and +/// typed. +/// +/// This class supports all of these use cases using simple type +/// polymorphism, and provides necessary support methods. Its interface +/// is RTTI-neutral. +//---------------------------------------------------------------------- +class ClangExpressionVariable : public ExpressionVariable +{ +public: + ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); + + ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags = EVNone); + + ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); + + ClangExpressionVariable(ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size); + + //---------------------------------------------------------------------- + /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /// Finds a variable by NamedDecl in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or NULL if that variable is not in the list. + //---------------------------------------------------------------------- + static ClangExpressionVariable * + FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id) + { + lldb::ExpressionVariableSP var_sp; + for (size_t index = 0, size = list.GetSize(); index < size; ++index) + { + var_sp = list.GetVariableAtIndex(index); + + if (ClangExpressionVariable *clang_var = llvm::dyn_cast(var_sp.get())) + { + ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id); + + if (parser_vars && parser_vars->m_named_decl == decl) + return clang_var; + } + } + return nullptr; + } + + //---------------------------------------------------------------------- + /// If the variable contains its own data, make a Value point at it. + /// If \a exe_ctx in not NULL, the value will be resolved in with + /// that execution context. + /// + /// @param[in] value + /// The value to point at the data. + /// + /// @param[in] exe_ctx + /// The execution context to use to resolve \a value. + /// + /// @return + /// True on success; false otherwise (in particular, if this variable + /// does not contain its own data). + //---------------------------------------------------------------------- + bool + PointValueAtData(Value &value, ExecutionContext *exe_ctx); + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + + ParserVars() : + m_parser_type(), + m_named_decl (NULL), + m_llvm_value (NULL), + m_lldb_value (), + m_lldb_var (), + m_lldb_sym (NULL) + { + } + + TypeFromParser m_parser_type; ///< The type of the variable according to the parser + const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable + llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue + lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable + lldb::VariableSP m_lldb_var; ///< The original variable for this variable + const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol + }; + +private: + typedef std::map ParserVarMap; + ParserVarMap m_parser_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable by the parser by allocating space for + /// parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars(uint64_t parser_id) + { + m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars(uint64_t parser_id) + { + m_parser_vars.erase(parser_id); + } + + //---------------------------------------------------------------------- + /// Access parser-specific variables + //---------------------------------------------------------------------- + ParserVars * + GetParserVars(uint64_t parser_id) + { + ParserVarMap::iterator i = m_parser_vars.find(parser_id); + + if (i == m_parser_vars.end()) + return NULL; + else + return &i->second; + } + + //---------------------------------------------------------------------- + /// The following values are valid if the variable is used by JIT code + //---------------------------------------------------------------------- + struct JITVars { + JITVars () : + m_alignment (0), + m_size (0), + m_offset (0) + { + } + + lldb::offset_t m_alignment; ///< The required alignment of the variable, in bytes + size_t m_size; ///< The space required for the variable, in bytes + lldb::offset_t m_offset; ///< The offset of the variable in the struct, in bytes + }; + +private: + typedef std::map JITVarMap; + JITVarMap m_jit_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable for materializing for the JIT by allocating + /// space for JIT-specific variables + //---------------------------------------------------------------------- + void + EnableJITVars(uint64_t parser_id) + { + m_jit_vars.insert(std::make_pair(parser_id, JITVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate JIT-specific variables + //---------------------------------------------------------------------- + void + DisableJITVars(uint64_t parser_id) + { + m_jit_vars.erase(parser_id); + } + + JITVars *GetJITVars(uint64_t parser_id) + { + JITVarMap::iterator i = m_jit_vars.find(parser_id); + + if (i == m_jit_vars.end()) + return NULL; + else + return &i->second; + } + + TypeFromUser + GetTypeFromUser (); + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const ExpressionVariable *ev) + { + return ev->getKind() == ExpressionVariable::eKindClang; + } + + //---------------------------------------------------------------------- + /// Members + //---------------------------------------------------------------------- + DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionVariable_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp new file mode 100644 index 000000000000..0d0d7475a00e --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -0,0 +1,221 @@ +//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangFunctionCaller.h" + +#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" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/Module.h" + +// Project includes +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/State.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb_private; + +//---------------------------------------------------------------------- +// ClangFunctionCaller constructor +//---------------------------------------------------------------------- +ClangFunctionCaller::ClangFunctionCaller +( + ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& functionAddress, + const ValueList &arg_value_list, + const char *name +) : + FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), + m_type_system_helper (*this) +{ + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a ClangFunctionCaller without a process. + assert (m_jit_process_wp.lock()); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangFunctionCaller::~ClangFunctionCaller() +{ +} + +unsigned +ClangFunctionCaller::CompileFunction (Stream &errors) +{ + if (m_compiled) + return 0; + + // FIXME: How does clang tell us there's no return value? We need to handle that case. + unsigned num_errors = 0; + + std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); + + // Cons up the function we're going to wrap our call in, then compile it... + // We declare the function "extern "C"" because the compiler might be in C++ + // mode which would mangle the name and then we couldn't find it again... + m_wrapper_function_text.clear(); + m_wrapper_function_text.append ("extern \"C\" void "); + m_wrapper_function_text.append (m_wrapper_function_name); + m_wrapper_function_text.append (" (void *input)\n{\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" \n {\n"); + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" (*fn_ptr) ("); + + // Get the number of arguments. If we have a function type and it is prototyped, + // trust that, otherwise use the values we were given. + + // FIXME: This will need to be extended to handle Variadic functions. We'll need + // to pull the defined arguments out of the function, then add the types from the + // arguments list for the variable arguments. + + uint32_t num_args = UINT32_MAX; + bool trust_function = false; + // GetArgumentCount returns -1 for an unprototyped function. + CompilerType function_clang_type; + if (m_function_ptr) + { + function_clang_type = m_function_ptr->GetCompilerType(); + if (function_clang_type) + { + int num_func_args = function_clang_type.GetFunctionArgumentCount(); + if (num_func_args >= 0) + { + trust_function = true; + num_args = num_func_args; + } + } + } + + if (num_args == UINT32_MAX) + num_args = m_arg_values.GetSize(); + + std::string args_buffer; // This one stores the definition of all the args in "struct caller". + std::string args_list_buffer; // This one stores the argument list called from the structure. + for (size_t i = 0; i < num_args; i++) + { + std::string type_name; + + if (trust_function) + { + type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); + } + else + { + CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); + if (clang_qual_type) + { + type_name = clang_qual_type.GetTypeName().AsCString(""); + } + else + { + errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + return 1; + } + } + + m_wrapper_function_text.append (type_name); + if (i < num_args - 1) + m_wrapper_function_text.append (", "); + + char arg_buf[32]; + args_buffer.append (" "); + args_buffer.append (type_name); + snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); + args_buffer.push_back (' '); + args_buffer.append (arg_buf); + args_buffer.append (";\n"); + + args_list_buffer.append ("__lldb_fn_data->"); + args_list_buffer.append (arg_buf); + if (i < num_args - 1) + args_list_buffer.append (", "); + + } + m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. + + m_wrapper_function_text.append (args_buffer); + + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" return_value;"); + m_wrapper_function_text.append ("\n };\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" *) input;\n"); + + m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); + m_wrapper_function_text.append (args_list_buffer); + m_wrapper_function_text.append (");\n}\n"); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + + // Okay, now compile this expression + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + if (jit_process_sp) + { + const bool generate_debug_info = true; + m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); + + num_errors = m_parser->Parse (errors); + } + else + { + errors.Printf("no process - unable to inject function"); + num_errors = 1; + } + + m_compiled = (num_errors == 0); + + if (!m_compiled) + return num_errors; + + return num_errors; +} + +clang::ASTConsumer * +ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); + + return m_struct_extractor.get(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h new file mode 100644 index 000000000000..3e30f818a932 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -0,0 +1,173 @@ +//===-- ClangFunctionCaller.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_ClangFunctionCaller_h_ +#define liblldb_ClangFunctionCaller_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Process.h" + +namespace lldb_private +{ + +class ASTStructExtractor; +class ClangExpressionParser; + +//---------------------------------------------------------------------- +/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h" +/// @brief Encapsulates a function that can be called. +/// +/// A given ClangFunctionCaller object can handle a single function signature. +/// Once constructed, it can set up any number of concurrent calls to +/// functions with that signature. +/// +/// It performs the call by synthesizing a structure that contains the pointer +/// to the function and the arguments that should be passed to that function, +/// and producing a special-purpose JIT-compiled function that accepts a void* +/// pointing to this struct as its only argument and calls the function in the +/// struct with the written arguments. This method lets Clang handle the +/// vagaries of function calling conventions. +/// +/// The simplest use of the ClangFunctionCaller is to construct it with a +/// function representative of the signature you want to use, then call +/// ExecuteFunction(ExecutionContext &, Stream &, Value &). +/// +/// If you need to reuse the arguments for several calls, you can call +/// InsertFunction() followed by WriteFunctionArguments(), which will return +/// the location of the args struct for the wrapper function in args_addr_ref. +/// +/// If you need to call the function on the thread plan stack, you can also +/// call InsertFunction() followed by GetThreadPlanToCallFunction(). +/// +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed +/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// and its address returned in that variable. +/// +/// Any of the methods that take arg_addr_ptr can be passed NULL, and the +/// argument space will be managed for you. +//---------------------------------------------------------------------- +class ClangFunctionCaller : public FunctionCaller +{ + friend class ASTStructExtractor; + + class ClangFunctionCallerHelper : public ClangExpressionHelper + { + public: + ClangFunctionCallerHelper (ClangFunctionCaller &owner) : + m_owner(owner) + { + } + + ~ClangFunctionCallerHelper() override = default; + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + private: + ClangFunctionCaller &m_owner; + std::unique_ptr m_struct_extractor; ///< The class that generates the argument struct layout. + }; + +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunctionCaller (ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name); + + ~ClangFunctionCaller() override; + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] errors + /// The stream to print parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + unsigned + CompileFunction (Stream &errors) override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + +protected: + const char *GetWrapperStructName() + { + return m_wrapper_struct_name.c_str(); + } + +private: + //------------------------------------------------------------------ + // For ClangFunctionCaller only + //------------------------------------------------------------------ + + // Note: the parser needs to be destructed before the execution unit, so + // declare the execution unit first. + ClangFunctionCallerHelper m_type_system_helper; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangFunctionCaller_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp new file mode 100644 index 000000000000..05d8a320a5a4 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -0,0 +1,731 @@ +//===-- ClangModulesDeclVendor.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 + +// Other libraries and framework includes +#include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Lookup.h" +#include "clang/Serialization/ASTReader.h" + +// Project includes +#include "ClangModulesDeclVendor.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" + +using namespace lldb_private; + +namespace { + // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings + // so we can provide them to the user in case a module failed to load. + class StoringDiagnosticConsumer : public clang::DiagnosticConsumer + { + public: + StoringDiagnosticConsumer (); + + void + HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &info) override; + + void + ClearDiagnostics (); + + void + DumpDiagnostics (Stream &error_stream); + + private: + typedef std::pair IDAndDiagnostic; + std::vector m_diagnostics; + Log * m_log; + }; + + // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required + // to load modules. + class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor + { + public: + ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser); + + ~ClangModulesDeclVendorImpl() override = default; + + bool + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) override; + + bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) override; + + uint32_t + FindDecls(const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) override; + + void + ForEachMacro(const ModuleVector &modules, + std::function handler) override; + + private: + void + ReportModuleExportsHelper (std::set &exports, + clang::Module *module); + + void + ReportModuleExports (ModuleVector &exports, + clang::Module *module); + + clang::ModuleLoadResult + DoGetModule(clang::ModuleIdPath path, bool make_visible); + + bool m_enabled = false; + + llvm::IntrusiveRefCntPtr m_diagnostics_engine; + llvm::IntrusiveRefCntPtr m_compiler_invocation; + std::unique_ptr m_compiler_instance; + std::unique_ptr m_parser; + size_t m_source_location_index = 0; // used to give name components fake SourceLocations + + typedef std::vector ImportedModule; + typedef std::map ImportedModuleMap; + typedef std::set ImportedModuleSet; + ImportedModuleMap m_imported_modules; + ImportedModuleSet m_user_imported_modules; + }; +} // anonymous namespace + +StoringDiagnosticConsumer::StoringDiagnosticConsumer () +{ + m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); +} + +void +StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) +{ + llvm::SmallVector diagnostic_string; + + info.FormatDiagnostic(diagnostic_string); + + m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); +} + +void +StoringDiagnosticConsumer::ClearDiagnostics () +{ + m_diagnostics.clear(); +} + +void +StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) +{ + for (IDAndDiagnostic &diag : m_diagnostics) + { + switch (diag.first) + { + default: + error_stream.PutCString(diag.second.c_str()); + error_stream.PutChar('\n'); + break; + case clang::DiagnosticsEngine::Level::Ignored: + break; + } + } +} + +static FileSpec +GetResourceDir () +{ + static FileSpec g_cached_resource_dir; + + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, [](){ + HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); + }); + + return g_cached_resource_dir; +} + +ClangModulesDeclVendor::ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendor::~ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser) : + ClangModulesDeclVendor(), + m_diagnostics_engine(diagnostics_engine), + m_compiler_invocation(compiler_invocation), + m_compiler_instance(std::move(compiler_instance)), + m_parser(std::move(parser)), + m_imported_modules() +{ +} + +void +ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set &exports, + clang::Module *module) +{ + if (exports.count(reinterpret_cast(module))) + return; + + exports.insert(reinterpret_cast(module)); + + llvm::SmallVector sub_exports; + + module->getExportedModules(sub_exports); + + for (clang::Module *module : sub_exports) + { + ReportModuleExportsHelper(exports, module); + } +} + +void +ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports, + clang::Module *module) +{ + std::set exports_set; + + ReportModuleExportsHelper(exports_set, module); + + for (ModuleID module : exports_set) + { + exports.push_back(module); + } +} + +bool +ClangModulesDeclVendorImpl::AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) +{ + // Fail early. + + if (m_compiler_instance->hadModuleLoaderFatalFailure()) + { + error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); + return false; + } + + // Check if we've already imported this module. + + std::vector imported_module; + + for (ConstString path_component : path) + { + imported_module.push_back(path_component); + } + + { + ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); + + if (mi != m_imported_modules.end()) + { + if (exported_modules) + { + ReportModuleExports(*exported_modules, mi->second); + } + return true; + } + } + + if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef())) + { + error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString()); + return false; + } + + llvm::SmallVector, 4> clang_path; + + { + clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); + + for (ConstString path_component : path) + { + clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()), + source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++))); + } + } + + StoringDiagnosticConsumer *diagnostic_consumer = static_cast(m_compiler_instance->getDiagnostics().getClient()); + + diagnostic_consumer->ClearDiagnostics(); + + clang::Module *top_level_module = DoGetModule(clang_path.front(), false); + + if (!top_level_module) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString()); + return false; + } + + clang::Module *submodule = top_level_module; + + for (size_t ci = 1; ci < path.size(); ++ci) + { + llvm::StringRef component = path[ci].GetStringRef(); + submodule = submodule->findSubmodule(component.str()); + if (!submodule) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); + return false; + } + } + + clang::Module *requested_module = DoGetModule(clang_path, true); + + if (requested_module != nullptr) + { + if (exported_modules) + { + ReportModuleExports(*exported_modules, requested_module); + } + + m_imported_modules[imported_module] = requested_module; + + m_enabled = true; + + return true; + } + + return false; +} + +bool +ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language) +{ + switch (language) + { + default: + return false; + // C++ and friends to be added + case lldb::LanguageType::eLanguageTypeC: + case lldb::LanguageType::eLanguageTypeC11: + case lldb::LanguageType::eLanguageTypeC89: + case lldb::LanguageType::eLanguageTypeC99: + case lldb::LanguageType::eLanguageTypeObjC: + return true; + } +} + +bool +ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu, + ClangModulesDeclVendor::ModuleVector &exported_modules, + Stream &error_stream) +{ + if (LanguageSupportsClangModules(cu.GetLanguage())) + { + std::vector imported_modules = cu.GetImportedModules(); + + for (ConstString imported_module : imported_modules) + { + std::vector path; + + path.push_back(imported_module); + + if (!AddModule(path, &exported_modules, error_stream)) + { + return false; + } + } + + return true; + } + + return true; +} + +// ClangImporter::lookupValue + +uint32_t +ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) +{ + if (!m_enabled) + { + return 0; + } + + if (!append) + decls.clear(); + + clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); + + clang::LookupResult lookup_result(m_compiler_instance->getSema(), + clang::DeclarationName(&ident), + clang::SourceLocation(), + clang::Sema::LookupOrdinaryName); + + m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); + + uint32_t num_matches = 0; + + for (clang::NamedDecl *named_decl : lookup_result) + { + if (num_matches >= max_matches) + return num_matches; + + decls.push_back(named_decl); + ++num_matches; + } + + return num_matches; +} + +void +ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules, + std::function handler) +{ + if (!m_enabled) + { + return; + } + + typedef std::map ModulePriorityMap; + ModulePriorityMap module_priorities; + + ssize_t priority = 0; + + for (ModuleID module : modules) + { + module_priorities[module] = priority++; + } + + if (m_compiler_instance->getPreprocessor().getExternalSource()) + { + m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros(); + } + + for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(), + me = m_compiler_instance->getPreprocessor().macro_end(); + mi != me; + ++mi) + { + const clang::IdentifierInfo *ii = nullptr; + + { + if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup()) + { + lookup->get(mi->first->getName()); + } + if (!ii) + { + ii = mi->first; + } + } + + ssize_t found_priority = -1; + clang::MacroInfo *macro_info = nullptr; + + for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) + { + clang::Module *module = module_macro->getOwningModule(); + + { + ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(module)); + + if (pi != module_priorities.end() && pi->second > found_priority) + { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } + + clang::Module *top_level_module = module->getTopLevelModule(); + + if (top_level_module != module) + { + ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(top_level_module)); + + if ((pi != module_priorities.end()) && pi->second > found_priority) + { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } + } + + if (macro_info) + { + std::string macro_expansion = "#define "; + macro_expansion.append(mi->first->getName().str().c_str()); + + { + if (macro_info->isFunctionLike()) + { + macro_expansion.append("("); + + bool first_arg = true; + + for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), + ae = macro_info->arg_end(); + ai != ae; + ++ai) + { + if (!first_arg) + { + macro_expansion.append(", "); + } + else + { + first_arg = false; + } + + macro_expansion.append((*ai)->getName().str()); + } + + if (macro_info->isC99Varargs()) + { + if (first_arg) + { + macro_expansion.append("..."); + } + else + { + macro_expansion.append(", ..."); + } + } + else if (macro_info->isGNUVarargs()) + { + macro_expansion.append("..."); + } + + macro_expansion.append(")"); + } + + macro_expansion.append(" "); + + bool first_token = true; + + for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), + te = macro_info->tokens_end(); + ti != te; + ++ti) + { + if (!first_token) + { + macro_expansion.append(" "); + } + else + { + first_token = false; + } + + if (ti->isLiteral()) + { + if (const char *literal_data = ti->getLiteralData()) + { + std::string token_str(literal_data, ti->getLength()); + macro_expansion.append(token_str); + } + else + { + bool invalid = false; + const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid); + + if (invalid) + { + lldbassert(!"Unhandled token kind"); + macro_expansion.append(""); + } + else + { + macro_expansion.append(std::string(literal_source, ti->getLength())); + } + } + } + else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind())) + { + macro_expansion.append(punctuator_spelling); + } + else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind())) + { + macro_expansion.append(keyword_spelling); + } + else + { + switch (ti->getKind()) + { + case clang::tok::TokenKind::identifier: + macro_expansion.append(ti->getIdentifierInfo()->getName().str()); + break; + case clang::tok::TokenKind::raw_identifier: + macro_expansion.append(ti->getRawIdentifier().str()); + default: + macro_expansion.append(ti->getName()); + break; + } + } + } + + if (handler(macro_expansion)) + { + return; + } + } + } + } +} + +clang::ModuleLoadResult +ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, + bool make_visible) +{ + clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; + + const bool is_inclusion_directive = false; + + return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); +} + +static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; + +lldb_private::ClangModulesDeclVendor * +ClangModulesDeclVendor::Create(Target &target) +{ + // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's + // compiler are both initialized in the same way – preferably by the same code. + + if (!target.GetPlatform()->SupportsModules()) + return nullptr; + + const ArchSpec &arch = target.GetArchitecture(); + + std::vector compiler_invocation_arguments = + { + "-fmodules", + "-fcxx-modules", + "-fsyntax-only", + "-femit-all-decls", + "-target", arch.GetTriple().str(), + "-fmodules-validate-system-headers", + "-Werror=non-modular-include-in-framework-module" + }; + + target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); + + compiler_invocation_arguments.push_back(ModuleImportBufferName); + + // Add additional search paths with { "-I", path } or { "-F", path } here. + + { + llvm::SmallString<128> DefaultModuleCache; + const bool erased_on_reboot = false; + llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); + llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + std::string module_cache_argument("-fmodules-cache-path="); + module_cache_argument.append(DefaultModuleCache.str().str()); + compiler_invocation_arguments.push_back(module_cache_argument); + } + + FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); + + for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) + { + const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); + + std::string search_path_argument = "-I"; + search_path_argument.append(search_path.GetPath()); + + compiler_invocation_arguments.push_back(search_path_argument); + } + + { + FileSpec clang_resource_dir = GetResourceDir(); + + if (clang_resource_dir.IsDirectory()) + { + compiler_invocation_arguments.push_back("-resource-dir"); + compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); + } + } + + llvm::IntrusiveRefCntPtr diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, + new StoringDiagnosticConsumer); + + std::vector compiler_invocation_argument_cstrs; + + for (const std::string &arg : compiler_invocation_arguments) { + compiler_invocation_argument_cstrs.push_back(arg.c_str()); + } + + llvm::IntrusiveRefCntPtr invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); + + if (!invocation) + return nullptr; + + std::unique_ptr source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", + ModuleImportBufferName); + + invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); + + std::unique_ptr instance(new clang::CompilerInstance); + + instance->setDiagnostics(diagnostics_engine.get()); + instance->setInvocation(invocation.get()); + + std::unique_ptr action(new clang::SyntaxOnlyAction); + + instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); + + if (!instance->hasTarget()) + return nullptr; + + instance->getTarget().adjust(instance->getLangOpts()); + + if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) + return nullptr; + + instance->getPreprocessor().enableIncrementalProcessing(); + + instance->createModuleManager(); + + instance->createSema(action->getTranslationUnitKind(), nullptr); + + const bool skipFunctionBodies = false; + std::unique_ptr parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); + + instance->getPreprocessor().EnterMainSourceFile(); + parser->Initialize(); + + clang::Parser::DeclGroupPtrTy parsed; + + while (!parser->ParseTopLevelDecl(parsed)); + + return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h new file mode 100644 index 000000000000..df3b20550f9a --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -0,0 +1,128 @@ +//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangModulesDeclVendor_h +#define liblldb_ClangModulesDeclVendor_h + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" +#include "lldb/Target/Platform.h" + +#include +#include + +namespace lldb_private +{ + +class ClangModulesDeclVendor : public DeclVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangModulesDeclVendor(); + + ~ClangModulesDeclVendor() override; + + static ClangModulesDeclVendor * + Create(Target &target); + + typedef std::vector ModulePath; + typedef uintptr_t ModuleID; + typedef std::vector ModuleVector; + + //------------------------------------------------------------------ + /// Add a module to the list of modules to search. + /// + /// @param[in] path + /// The path to the exact module to be loaded. E.g., if the desired + /// module is std.io, then this should be { "std", "io" }. + /// + /// @param[in] exported_modules + /// If non-NULL, a pointer to a vector to populate with the ID of every + /// module that is re-exported by the specified module. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the module. + /// + /// @return + /// True if the module could be loaded; false if not. If the + /// compiler encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Add all modules referred to in a given compilation unit to the list + /// of modules to search. + /// + /// @param[in] cu + /// The compilation unit to scan for imported modules. + /// + /// @param[in] exported_modules + /// A vector to populate with the ID of each module loaded (directly + /// and via re-exports) in this way. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the modules. + /// + /// @return + /// True if all modules referred to by the compilation unit could be + /// loaded; false if one could not be loaded. If the compiler + /// encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Enumerate all the macros that are defined by a given set of modules + /// that are already imported. + /// + /// @param[in] modules + /// The unique IDs for all modules to query. Later modules have higher + /// priority, just as if you @imported them in that order. This matters + /// if module A #defines a macro and module B #undefs it. + /// + /// @param[in] handler + /// A function to call with the text of each #define (including the + /// #define directive). #undef directives are not included; we simply + /// elide any corresponding #define. If this function returns true, + /// we stop the iteration immediately. + //------------------------------------------------------------------ + virtual void + ForEachMacro(const ModuleVector &modules, + std::function handler) = 0; + + //------------------------------------------------------------------ + /// Query whether Clang supports modules for a particular language. + /// LLDB uses this to decide whether to try to find the modules loaded + /// by a gaiven compile unit. + /// + /// @param[in] language + /// The language to query for. + /// + /// @return + /// True if Clang has modules for the given language. + //------------------------------------------------------------------ + static bool + LanguageSupportsClangModules (lldb::LanguageType language); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangModulesDeclVendor_h diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp new file mode 100644 index 000000000000..9bf9d435d7ea --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -0,0 +1,84 @@ +//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangPersistentVariables.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Value.h" + +#include "llvm/ADT/StringMap.h" + +using namespace lldb; +using namespace lldb_private; + +ClangPersistentVariables::ClangPersistentVariables () : + lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), + m_next_persistent_variable_id (0) +{ +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) +{ + return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp)); +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const CompilerType& compiler_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) +{ + return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size)); +} + +void +ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable) +{ + RemoveVariable(variable); + + const char *name = variable->GetName().AsCString(); + + if (*name != '$') + return; + name++; + + if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) + m_next_persistent_variable_id--; +} + +ConstString +ClangPersistentVariables::GetNextPersistentVariableName () +{ + char name_cstr[256]; + ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++); + ConstString name(name_cstr); + return name; +} + +void +ClangPersistentVariables::RegisterPersistentType (const ConstString &name, + clang::TypeDecl *type_decl) +{ + m_persistent_types.insert(std::pair(name.GetCString(), type_decl)); +} + +clang::TypeDecl * +ClangPersistentVariables::GetPersistentType (const ConstString &name) +{ + PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString()); + + if (i == m_persistent_types.end()) + return NULL; + else + return i->second; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h new file mode 100644 index 000000000000..0e03d013d049 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -0,0 +1,106 @@ +//===-- ClangPersistentVariables.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_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" + +#include "lldb/Expression/ExpressionVariable.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between expression invocations. +/// +/// A list of variables that can be accessed and updated by any expression. See +/// ClangPersistentVariable for more discussion. Also provides an increasing, +/// 0-based counter for naming result variables. +//---------------------------------------------------------------------- +class ClangPersistentVariables : public PersistentExpressionState +{ +public: + ClangPersistentVariables(); + + ~ClangPersistentVariables() override = default; + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const PersistentExpressionState *pv) + { + return pv->getKind() == PersistentExpressionState::eKindClang; + } + + lldb::ExpressionVariableSP + CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override; + + lldb::ExpressionVariableSP + CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const CompilerType& compiler_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) override; + + //---------------------------------------------------------------------- + /// Return the next entry in the sequence of strings "$0", "$1", ... for + /// use naming persistent expression convenience variables. + /// + /// @return + /// A string that contains the next persistent variable name. + //---------------------------------------------------------------------- + ConstString + GetNextPersistentVariableName () override; + + void + RemovePersistentVariable (lldb::ExpressionVariableSP variable) override; + + lldb::addr_t + LookupSymbol (const ConstString &name) override { return LLDB_INVALID_ADDRESS; } + + void + RegisterPersistentType (const ConstString &name, + clang::TypeDecl *tag_decl); + + clang::TypeDecl * + GetPersistentType (const ConstString &name); + + void + AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) + { + m_hand_loaded_clang_modules.push_back(module); + } + + const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() + { + return m_hand_loaded_clang_modules; + } + +private: + uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). + + typedef llvm::DenseMap PersistentTypeMap; + PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. + + ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- + ///< priority source for macros. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangPersistentVariables_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp new file mode 100644 index 000000000000..11f7f84ff5f1 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -0,0 +1,673 @@ +//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#if HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include + +#include "ClangUserExpression.h" + +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +using namespace lldb_private; + +ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options) : + LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options), + m_type_system_helper(*m_target_wp.lock().get()) +{ + switch (m_language) + { + case lldb::eLanguageTypeC_plus_plus: + m_allow_cxx = true; + break; + case lldb::eLanguageTypeObjC: + m_allow_objc = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + default: + m_allow_cxx = true; + m_allow_objc = true; + break; + } +} + +ClangUserExpression::~ClangUserExpression () +{ +} + +void +ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangUserExpression::ScanContext()"); + + m_target = exe_ctx.GetTargetPtr(); + + if (!(m_allow_cxx || m_allow_objc)) + { + if (log) + log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); + return; + } + + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame == NULL) + { + if (log) + log->Printf(" [CUE::SC] Null stack frame"); + return; + } + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + + if (!sym_ctx.function) + { + if (log) + log->Printf(" [CUE::SC] Null function"); + return; + } + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + { + if (log) + log->Printf(" [CUE::SC] Null function block"); + return; + } + + CompilerDeclContext decl_context = function_block->GetDeclContext(); + + if (!decl_context) + { + if (log) + log->Printf(" [CUE::SC] Null decl context"); + return; + } + + if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) + { + if (m_allow_cxx && method_decl->isInstance()) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(thisErrorString); + return; + } + + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || + !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(thisErrorString); + return; + } + } + + m_in_cplusplus_method = true; + m_needs_object_ptr = true; + } + } + else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context)) + { + if (m_allow_objc) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(selfErrorString); + return; + } + + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(selfErrorString); + return; + } + } + + m_in_objectivec_method = true; + m_needs_object_ptr = true; + + if (!method_decl->isInstanceMethod()) + m_in_static_method = true; + } + } + else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) + { + // We might also have a function that said in the debug information that it captured an + // object pointer. The best way to deal with getting to the ivars at present is by pretending + // that this is a method of a class in whatever runtime the debug info says the object pointer + // belongs to. Do that here. + + ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl); + if (metadata && metadata->HasObjectPtr()) + { + lldb::LanguageType language = metadata->GetObjectPtrLanguage(); + if (language == lldb::eLanguageTypeC_plus_plus) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(thisErrorString); + return; + } + + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || + !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(thisErrorString); + return; + } + } + + m_in_cplusplus_method = true; + m_needs_object_ptr = true; + } + else if (language == lldb::eLanguageTypeObjC) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(selfErrorString); + return; + } + + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(selfErrorString); + return; + } + + Type *self_type = self_variable_sp->GetType(); + + if (!self_type) + { + err.SetErrorString(selfErrorString); + return; + } + + CompilerType self_clang_type = self_type->GetForwardCompilerType (); + + if (!self_clang_type) + { + err.SetErrorString(selfErrorString); + return; + } + + if (ClangASTContext::IsObjCClassType(self_clang_type)) + { + return; + } + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) + { + m_in_objectivec_method = true; + m_needs_object_ptr = true; + } + else + { + err.SetErrorString(selfErrorString); + return; + } + } + else + { + m_in_objectivec_method = true; + m_needs_object_ptr = true; + } + } + } + } +} + +// This is a really nasty hack, meant to fix Objective-C expressions of the form +// (int)[myArray count]. Right now, because the type information for count is +// not available, [myArray count] returns id, which can't be directly cast to +// int without causing a clang error. +static void +ApplyObjcCastHack(std::string &expr) +{ +#define OBJC_CAST_HACK_FROM "(int)[" +#define OBJC_CAST_HACK_TO "(int)(long long)[" + + size_t from_offset; + + while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) + expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); + +#undef OBJC_CAST_HACK_TO +#undef OBJC_CAST_HACK_FROM +} + +bool +ClangUserExpression::Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Error err; + + InstallContext(exe_ctx); + + if (Target *target = exe_ctx.GetTargetPtr()) + { + if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) + { + m_result_delegate.RegisterPersistentState(persistent_state); + } + else + { + error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + return false; + } + } + else + { + error_stream.PutCString ("error: couldn't start parsing (no target)"); + return false; + } + + ScanContext(exe_ctx, err); + + if (!err.Success()) + { + error_stream.Printf("warning: %s\n", err.AsCString()); + } + + StreamString m_transformed_stream; + + //////////////////////////////////// + // Generate the expression + // + + ApplyObjcCastHack(m_expr_text); + //ApplyUnicharHack(m_expr_text); + + std::string prefix = m_expr_prefix; + + if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) + { + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules(); + ClangModulesDeclVendor::ModuleVector modules_for_macros; + + for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) + { + modules_for_macros.push_back(module); + } + + if (m_target->GetEnableAutoImportClangModules()) + { + if (StackFrame *frame = exe_ctx.GetFramePtr()) + { + if (Block *block = frame->GetFrameBlock()) + { + SymbolContext sc; + + block->CalculateSymbolContext(&sc); + + if (sc.comp_unit) + { + StreamString error_stream; + + decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); + } + } + } + } + } + + std::unique_ptr source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); + + lldb::LanguageType lang_type; + + if (m_in_cplusplus_method) + lang_type = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + lang_type = lldb::eLanguageTypeObjC; + else + lang_type = lldb::eLanguageTypeC; + + if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) + { + error_stream.PutCString ("error: couldn't construct expression body"); + return false; + } + + if (log) + log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + + //////////////////////////////////// + // Set up the target and compiler + // + + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + { + error_stream.PutCString ("error: invalid target\n"); + return false; + } + + ////////////////////////// + // Parse the expression + // + + m_materializer_ap.reset(new Materializer()); + + ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); + + class OnExit + { + public: + typedef std::function Callback; + + OnExit (Callback const &callback) : + m_callback(callback) + { + } + + ~OnExit () + { + m_callback(); + } + private: + Callback m_callback; + }; + + OnExit on_exit([this]() { ResetDeclMap(); }); + + if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) + { + error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + + return false; + } + + Process *process = exe_ctx.GetProcessPtr(); + ExecutionContextScope *exe_scope = process; + + if (!exe_scope) + exe_scope = exe_ctx.GetTargetPtr(); + + ClangExpressionParser parser(exe_scope, *this, generate_debug_info); + + unsigned num_errors = parser.Parse (error_stream); + + if (num_errors) + { + error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + + return false; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // Prepare the output of the parser for execution, evaluating it statically if possible + // + + Error jit_error = parser.PrepareForExecution (m_jit_start_addr, + m_jit_end_addr, + m_execution_unit_sp, + exe_ctx, + m_can_interpret, + execution_policy); + + if (generate_debug_info) + { + lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) + { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); + } +// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); +// StreamFile strm (stdout, false); +// if (jit_obj_file) +// { +// jit_obj_file->GetSectionList(); +// jit_obj_file->GetSymtab(); +// jit_obj_file->Dump(&strm); +// } +// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); +// if (jit_sym_vendor) +// { +// lldb_private::SymbolContextList sc_list; +// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); +// sc_list.Dump(&strm, target); +// jit_sym_vendor->Dump(&strm); +// } + } + + ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. + + if (jit_error.Success()) + { + if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) + m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + return true; + } + else + { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf ("error: %s\n", error_cstr); + else + error_stream.Printf ("error: expression can't be interpreted or run\n"); + return false; + } +} + +bool +ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, + std::vector &args, + lldb::addr_t struct_address, + Stream &error_stream) +{ + lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + + if (m_needs_object_ptr) + { + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + if (!frame_sp) + return true; + + ConstString object_name; + + if (m_in_cplusplus_method) + { + object_name.SetCString("this"); + } + else if (m_in_objectivec_method) + { + object_name.SetCString("self"); + } + else + { + error_stream.Printf("Need object pointer but don't know the language\n"); + return false; + } + + Error object_ptr_error; + + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + + if (!object_ptr_error.Success()) + { + error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + object_ptr = 0; + } + + if (m_in_objectivec_method) + { + ConstString cmd_name("_cmd"); + + cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); + + if (!object_ptr_error.Success()) + { + error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + cmd_ptr = 0; + } + } + if (object_ptr) + args.push_back(object_ptr); + + if (m_in_objectivec_method) + args.push_back(cmd_ptr); + + args.push_back(struct_address); + } + else + { + args.push_back(struct_address); + } + return true; +} + +lldb::ExpressionVariableSP +ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope) +{ + return m_result_delegate.GetVariable(); +} + +void +ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory) +{ + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx)); +} + +clang::ASTConsumer * +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, + m_target)); + + return m_result_synthesizer_up.get(); +} + +ClangUserExpression::ResultDelegate::ResultDelegate() +{ +} + +ConstString +ClangUserExpression::ResultDelegate::GetName() +{ + return m_persistent_state->GetNextPersistentVariableName(); +} + +void +ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable) +{ + m_variable = variable; +} + +void +ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state) +{ + m_persistent_state = persistent_state; +} + +lldb::ExpressionVariableSP & +ClangUserExpression::ResultDelegate::GetVariable() +{ + return m_variable; +} + diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h new file mode 100644 index 000000000000..f2bfe31dce09 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -0,0 +1,218 @@ +//===-- ClangUserExpression.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_ClangUserExpression_h_ +#define liblldb_ClangUserExpression_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "ASTStructExtractor.h" +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionVariable.h" +#include "IRForTarget.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/LLVMUserExpression.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUserExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangUserExpression : public LLVMUserExpression +{ +public: + enum { kDefaultTimeout = 500000u }; + + class ClangUserExpressionHelper : public ClangExpressionHelper + { + public: + ClangUserExpressionHelper (Target &target) : + m_target(target) + { + } + + ~ClangUserExpressionHelper() override = default; + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + private: + Target &m_target; + std::unique_ptr m_expr_decl_map_up; + std::unique_ptr m_struct_extractor_up; ///< The class that generates the argument struct layout. + std::unique_ptr m_result_synthesizer_up; + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options); + + ~ClangUserExpression() override; + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool + Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap () + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory); + } + + lldb::ExpressionVariableSP + GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; + +private: + //------------------------------------------------------------------ + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. + //------------------------------------------------------------------ + + void + ScanContext (ExecutionContext &exe_ctx, + lldb_private::Error &err) override; + + bool + AddArguments (ExecutionContext &exe_ctx, + std::vector &args, + lldb::addr_t struct_address, + Stream &error_stream) override; + + ClangUserExpressionHelper m_type_system_helper; + + class ResultDelegate : public Materializer::PersistentVariableDelegate + { + public: + ResultDelegate(); + ConstString GetName() override; + void DidDematerialize(lldb::ExpressionVariableSP &variable) override; + + void RegisterPersistentState(PersistentExpressionState *persistent_state); + lldb::ExpressionVariableSP &GetVariable(); + + private: + PersistentExpressionState *m_persistent_state; + lldb::ExpressionVariableSP m_variable; + }; + + ResultDelegate m_result_delegate; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUserExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp new file mode 100644 index 000000000000..fe044c17ac78 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -0,0 +1,189 @@ +//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangUtilityFunction.h" + +// C Includes +#include +#if HAVE_SYS_TYPES_H +# include +#endif + +// C++ Includes + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +//------------------------------------------------------------------ +/// Constructor +/// +/// @param[in] text +/// The text of the function. Must be a full translation unit. +/// +/// @param[in] name +/// The name of the function, as used in the text. +//------------------------------------------------------------------ +ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name) : + UtilityFunction (exe_scope, text, name) +{ +} + +ClangUtilityFunction::~ClangUtilityFunction () +{ +} + +//------------------------------------------------------------------ +/// Install the utility function into a process +/// +/// @param[in] error_stream +/// A stream to print parse errors and warnings to. +/// +/// @param[in] exe_ctx +/// The execution context to install the utility function to. +/// +/// @return +/// True on success (no errors); false otherwise. +//------------------------------------------------------------------ +bool +ClangUtilityFunction::Install (Stream &error_stream, + ExecutionContext &exe_ctx) +{ + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) + { + error_stream.PutCString("error: already installed\n"); + return false; + } + + //////////////////////////////////// + // Set up the target and compiler + // + + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + { + error_stream.PutCString ("error: invalid target\n"); + return false; + } + + Process *process = exe_ctx.GetProcessPtr(); + + if (!process) + { + error_stream.PutCString ("error: invalid process\n"); + return false; + } + + ////////////////////////// + // Parse the expression + // + + bool keep_result_in_memory = false; + + ResetDeclMap(exe_ctx, keep_result_in_memory); + + if (!DeclMap()->WillParse(exe_ctx, NULL)) + { + error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + return false; + } + + const bool generate_debug_info = true; + ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); + + unsigned num_errors = parser.Parse (error_stream); + + if (num_errors) + { + error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + + ResetDeclMap(); + + return false; + } + + ////////////////////////////////// + // JIT the output of the parser + // + + bool can_interpret = false; // should stay that way + + Error jit_error = parser.PrepareForExecution (m_jit_start_addr, + m_jit_end_addr, + m_execution_unit_sp, + exe_ctx, + can_interpret, + eExecutionPolicyAlways); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) + { + m_jit_process_wp = process->shared_from_this(); + if (parser.GetGenerateDebugInfo()) + { + lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) + { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); + } + } + } + +#if 0 + // jingham: look here + StreamFile logfile ("/tmp/exprs.txt", "a"); + logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", + m_jit_start_addr, + m_function_name.c_str(), + m_function_text.c_str()); +#endif + + DeclMap()->DidParse(); + + ResetDeclMap(); + + if (jit_error.Success()) + { + return true; + } + else + { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf ("error: %s\n", error_cstr); + else + error_stream.Printf ("error: expression can't be interpreted or run\n"); + return false; + } +} + +void +ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) +{ + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h new file mode 100644 index 000000000000..74839717946b --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -0,0 +1,137 @@ +//===-- ClangUtilityFunction.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_ClangUtilityFunction_h_ +#define liblldb_ClangUtilityFunction_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/UtilityFunction.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUtilityFunction encapsulates +/// a self-contained function meant to be used from other code. Utility +/// functions can perform error-checking for ClangUserExpressions, or can +/// simply provide a way to push a function into the target for the debugger to +/// call later on. +//---------------------------------------------------------------------- +class ClangUtilityFunction : public UtilityFunction +{ +public: + class ClangUtilityFunctionHelper : public ClangExpressionHelper + { + public: + ClangUtilityFunctionHelper () + { + } + + ~ClangUtilityFunctionHelper() override {} + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override + { + return nullptr; + } + private: + std::unique_ptr m_expr_decl_map_up; + }; + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name); + + ~ClangUtilityFunction() override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap() + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + } + + bool + Install (Stream &error_stream, ExecutionContext &exe_ctx) override; + +private: + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUtilityFunction_h_ diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp new file mode 100644 index 000000000000..37b7bd1d2c84 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -0,0 +1,2820 @@ +//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IRForTarget.h" + +#include "ClangExpressionDeclMap.h" + +#include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueSymbolTable.h" + +#include "clang/AST/ASTContext.h" + +#include "lldb/Core/dwarf.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/CPPLanguageRuntime.h" + +#include + +using namespace llvm; + +static char ID; + +IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) : + m_execution_unit(execution_unit), + m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()), + m_allocation(LLDB_INVALID_ADDRESS) +{ +} + +IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : + m_maker(maker), + m_values() +{ +} + +IRForTarget::FunctionValueCache::~FunctionValueCache() +{ +} + +llvm::Value * +IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) +{ + if (!m_values.count(function)) + { + llvm::Value *ret = m_maker(function); + m_values[function] = ret; + return ret; + } + return m_values[function]; +} + +lldb::addr_t +IRForTarget::StaticDataAllocator::Allocate() +{ + lldb_private::Error err; + + if (m_allocation != LLDB_INVALID_ADDRESS) + { + m_execution_unit.FreeNow(m_allocation); + m_allocation = LLDB_INVALID_ADDRESS; + } + + m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err); + + return m_allocation; +} + +lldb::TargetSP +IRForTarget::StaticDataAllocator::GetTarget() +{ + return m_execution_unit.GetTarget(); +} + +static llvm::Value * +FindEntryInstruction (llvm::Function *function) +{ + if (function->empty()) + return NULL; + + return function->getEntryBlock().getFirstNonPHIOrDbg(); +} + +IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char *func_name) : + ModulePass(ID), + m_resolve_vars(resolve_vars), + m_func_name(func_name), + m_module(NULL), + m_decl_map(decl_map), + m_data_allocator(execution_unit), + m_CFStringCreateWithBytes(NULL), + m_sel_registerName(NULL), + m_intptr_ty(NULL), + m_error_stream(error_stream), + m_result_store(NULL), + m_result_is_pointer(false), + m_reloc_placeholder(NULL), + m_entry_instruction_finder (FindEntryInstruction) +{ +} + +/* Handy utility functions used at several places in the code */ + +static std::string +PrintValue(const Value *value, bool truncate = false) +{ + std::string s; + if (value) + { + raw_string_ostream rso(s); + value->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + } + return s; +} + +static std::string +PrintType(const llvm::Type *type, bool truncate = false) +{ + std::string s; + raw_string_ostream rso(s); + type->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; +} + +IRForTarget::~IRForTarget() +{ +} + +bool +IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) +{ + llvm_function.setLinkage(GlobalValue::ExternalLinkage); + + std::string name = llvm_function.getName().str(); + + return true; +} + +IRForTarget::LookupResult +IRForTarget::GetFunctionAddress (llvm::Function *fun, + uint64_t &fun_addr, + lldb_private::ConstString &name, + Constant **&value_ptr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + fun_addr = LLDB_INVALID_ADDRESS; + name.Clear(); + value_ptr = NULL; + + if (fun->isIntrinsic()) + { + Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID(); + + switch (intrinsic_id) + { + default: + if (log) + log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str()); + + return LookupResult::Fail; + case Intrinsic::memcpy: + { + static lldb_private::ConstString g_memcpy_str ("memcpy"); + name = g_memcpy_str; + } + break; + case Intrinsic::memset: + { + static lldb_private::ConstString g_memset_str ("memset"); + name = g_memset_str; + } + break; + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + return LookupResult::Ignore; + } + + if (log && name) + log->Printf("Resolved intrinsic name \"%s\"", name.GetCString()); + } + else + { + name.SetCStringWithLength (fun->getName().data(), fun->getName().size()); + } + + // Find the address of the function. + + clang::NamedDecl *fun_decl = DeclForGlobal (fun); + + if (fun_decl) + { + if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) + { + std::vector alternates; + bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); + if (!found_it) + { + if (log) + log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); + // Check for an alternate mangling for names from the standard library. + // For example, "std::basic_string<...>" has an alternate mangling scheme per + // the Itanium C++ ABI. + lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); + if (process_sp) + { + lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); + if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) + { + for (size_t i = 0; i < alternates.size(); ++i) + { + const lldb_private::ConstString &alternate_name = alternates[i]; + if (log) + log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) + { + if (log) + log->Printf("Found address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + break; + } + } + } + } + } + + if (!found_it) + { + lldb_private::Mangled mangled_name(name); + if (m_error_stream) + { + if (mangled_name.GetMangledName()) + m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), + mangled_name.GetMangledName().GetCString()); + else + m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); + } + return LookupResult::Fail; + } + } + } + else + { + if (!m_decl_map->GetFunctionAddress (name, fun_addr)) + { + if (log) + log->Printf ("Metadataless function \"%s\" had no address", name.GetCString()); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString()); + + return LookupResult::Fail; + } + } + + if (log) + log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); + + return LookupResult::Success; +} + +llvm::Constant * +IRForTarget::BuildFunctionPointer (llvm::Type *type, + uint64_t ptr) +{ + PointerType *fun_ptr_ty = PointerType::getUnqual(type); + Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false); + return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); +} + +void +IRForTarget::RegisterFunctionMetadata(LLVMContext &context, + llvm::Value *function_ptr, + const char *name) +{ + for (llvm::User *user : function_ptr->users()) + { + if (Instruction *user_inst = dyn_cast(user)) + { + MDString* md_name = MDString::get(context, StringRef(name)); + + MDNode *metadata = MDNode::get(context, md_name); + + user_inst->setMetadata("lldb.call.realName", metadata); + } + else + { + RegisterFunctionMetadata (context, user, name); + } + } +} + +bool +IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + for (llvm::Module::iterator fi = llvm_module.begin(); + fi != llvm_module.end(); + ++fi) + { + Function *fun = &*fi; + + bool is_decl = fun->isDeclaration(); + + if (log) + log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str()); + + if (!is_decl) + continue; + + if (fun->use_empty()) + continue; // ignore + + uint64_t addr = LLDB_INVALID_ADDRESS; + lldb_private::ConstString name; + Constant **value_ptr = NULL; + + LookupResult result = GetFunctionAddress(fun, + addr, + name, + value_ptr); + + switch (result) + { + case LookupResult::Fail: + return false; // GetFunctionAddress reports its own errors + + case LookupResult::Ignore: + break; // Nothing to do + + case LookupResult::Success: + { + Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr); + + RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString()); + + if (value_ptr) + *value_ptr = value; + + // If we are replacing a function with the nobuiltin attribute, it may + // be called with the builtin attribute on call sites. Remove any such + // attributes since it's illegal to have a builtin call to something + // other than a nobuiltin function. + if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) { + llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin); + + for (auto u : fun->users()) { + if (auto call = dyn_cast(u)) { + call->removeAttribute(AttributeSet::FunctionIndex, builtin); + } + } + } + + fun->replaceAllUsesWith(value); + } + break; + } + } + + return true; +} + + +clang::NamedDecl * +IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) +{ + NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); + + if (!named_metadata) + return NULL; + + unsigned num_nodes = named_metadata->getNumOperands(); + unsigned node_index; + + for (node_index = 0; + node_index < num_nodes; + ++node_index) + { + llvm::MDNode *metadata_node = dyn_cast(named_metadata->getOperand(node_index)); + if (!metadata_node) + return NULL; + + if (metadata_node->getNumOperands() != 2) + continue; + + if (mdconst::dyn_extract_or_null(metadata_node->getOperand(0)) != global_val) + continue; + + ConstantInt *constant_int = mdconst::dyn_extract(metadata_node->getOperand(1)); + + if (!constant_int) + return NULL; + + uintptr_t ptr = constant_int->getZExtValue(); + + return reinterpret_cast(ptr); + } + + return NULL; +} + +clang::NamedDecl * +IRForTarget::DeclForGlobal (GlobalValue *global_val) +{ + return DeclForGlobal(global_val, m_module); +} + +bool +IRForTarget::CreateResultVariable (llvm::Function &llvm_function) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_resolve_vars) + return true; + + // Find the result variable. If it doesn't exist, we can give up right here. + + ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + + std::string result_name_str; + const char *result_name = NULL; + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + result_name_str = vi->first().str(); + const char *value_name = result_name_str.c_str(); + + if (strstr(value_name, "$__lldb_expr_result_ptr") && + strncmp(value_name, "_ZGV", 4)) + { + result_name = value_name; + m_result_is_pointer = true; + break; + } + + if (strstr(value_name, "$__lldb_expr_result") && + strncmp(value_name, "_ZGV", 4)) + { + result_name = value_name; + m_result_is_pointer = false; + break; + } + } + + if (!result_name) + { + if (log) + log->PutCString("Couldn't find result variable"); + + return true; + } + + if (log) + log->Printf("Result name: \"%s\"", result_name); + + Value *result_value = m_module->getNamedValue(result_name); + + if (!result_value) + { + if (log) + log->PutCString("Result variable had no data"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); + + return false; + } + + if (log) + log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); + + GlobalVariable *result_global = dyn_cast(result_value); + + if (!result_global) + { + if (log) + log->PutCString("Result variable isn't a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); + + return false; + } + + clang::NamedDecl *result_decl = DeclForGlobal (result_global); + if (!result_decl) + { + if (log) + log->PutCString("Result variable doesn't have a corresponding Decl"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); + + return false; + } + + if (log) + { + std::string decl_desc_str; + raw_string_ostream decl_desc_stream(decl_desc_str); + result_decl->print(decl_desc_stream); + decl_desc_stream.flush(); + + log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); + } + + clang::VarDecl *result_var = dyn_cast(result_decl); + if (!result_var) + { + if (log) + log->PutCString("Result variable Decl isn't a VarDecl"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); + + return false; + } + + // Get the next available result name from m_decl_map and create the persistent + // variable for it + + // If the result is an Lvalue, it is emitted as a pointer; see + // ASTResultSynthesizer::SynthesizeBodyResult. + if (m_result_is_pointer) + { + clang::QualType pointer_qual_type = result_var->getType(); + const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); + + const clang::PointerType *pointer_pointertype = pointer_type->getAs(); + const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs(); + + if (pointer_pointertype) + { + clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); + + m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + else if (pointer_objcobjpointertype) + { + clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); + + m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + else + { + if (log) + log->PutCString("Expected result to have pointer type, but it did not"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); + + return false; + } + } + else + { + m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + + + lldb::TargetSP target_sp (m_data_allocator.GetTarget()); + lldb_private::ExecutionContext exe_ctx (target_sp, true); + if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) + { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); + + if (log) + log->Printf("Result type has size 0"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", + type_desc_stream.GetData()); + return false; + } + + if (log) + { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); + + log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); + } + + m_result_name = lldb_private::ConstString("$RESULT_NAME"); + + if (log) + log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, + m_result_name.GetCString(), + m_result_type.GetByteSize(nullptr)); + + // Construct a new result global and set up its metadata + + GlobalVariable *new_result_global = new GlobalVariable((*m_module), + result_global->getType()->getElementType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, + NULL, /* no initializer */ + m_result_name.GetCString ()); + + // It's too late in compilation to create a new VarDecl for this, but we don't + // need to. We point the metadata at the old VarDecl. This creates an odd + // anomaly: a variable with a Value whose name is something like $0 and a + // Decl whose name is $__lldb_expr_result. This condition is handled in + // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is + // fixed up. + + ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), + reinterpret_cast(result_decl), + false); + + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(new_result_global); + values[1] = ConstantAsMetadata::get(new_constant_int); + + ArrayRef value_ref(values, 2); + + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); + named_metadata->addOperand(persistent_global_md); + + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", + PrintValue(result_global).c_str(), + PrintValue(new_result_global).c_str()); + + if (result_global->use_empty()) + { + // We need to synthesize a store for this variable, because otherwise + // there's nothing to put into its equivalent persistent variable. + + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); + + if (!first_entry_instruction) + return false; + + if (!result_global->hasInitializer()) + { + if (log) + log->Printf("Couldn't find initializer for unused variable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); + + return false; + } + + Constant *initializer = result_global->getInitializer(); + + StoreInst *synthesized_store = new StoreInst(initializer, + new_result_global, + first_entry_instruction); + + if (log) + log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); + } + else + { + result_global->replaceAllUsesWith(new_result_global); + } + + if (!m_decl_map->AddPersistentVariable(result_decl, + m_result_name, + m_result_type, + true, + m_result_is_pointer)) + return false; + + result_global->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, + llvm::GlobalVariable *cstr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Type *ns_str_ty = ns_str->getType(); + + Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + Type *i32_ty = Type::getInt32Ty(m_module->getContext()); + Type *i8_ty = Type::getInt8Ty(m_module->getContext()); + + if (!m_CFStringCreateWithBytes) + { + lldb::addr_t CFStringCreateWithBytes_addr; + + static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); + + if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) + { + if (log) + log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); + + return false; + } + + if (log) + log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); + + // Build the function type: + // + // CFStringRef CFStringCreateWithBytes ( + // CFAllocatorRef alloc, + // const UInt8 *bytes, + // CFIndex numBytes, + // CFStringEncoding encoding, + // Boolean isExternalRepresentation + // ); + // + // We make the following substitutions: + // + // CFStringRef -> i8* + // CFAllocatorRef -> i8* + // UInt8 * -> i8* + // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) + // CFStringEncoding -> i32 + // Boolean -> i8 + + Type *arg_type_array[5]; + + arg_type_array[0] = i8_ptr_ty; + arg_type_array[1] = i8_ptr_ty; + arg_type_array[2] = m_intptr_ty; + arg_type_array[3] = i32_ty; + arg_type_array[4] = i8_ty; + + ArrayRef CFSCWB_arg_types(arg_type_array, 5); + + llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); + + // Build the constant containing the pointer to the function + PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); + Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); + m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); + } + + ConstantDataSequential *string_array = NULL; + + if (cstr) + string_array = dyn_cast(cstr->getInitializer()); + + Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); + Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); + Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); + Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ + Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ + + Value *argument_array[5]; + + argument_array[0] = alloc_arg; + argument_array[1] = bytes_arg; + argument_array[2] = numBytes_arg; + argument_array[3] = encoding_arg; + argument_array[4] = isExternal_arg; + + ArrayRef CFSCWB_arguments(argument_array, 5); + + FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { + return CallInst::Create(m_CFStringCreateWithBytes, + CFSCWB_arguments, + "CFStringCreateWithBytes", + llvm::cast(m_entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder)) + { + if (log) + log->PutCString("Couldn't replace the NSString with the result of the call"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n"); + + return false; + } + + ns_str->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCConstStrings() +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); + + if (strstr(value_name_cstr, "_unnamed_cfstring_")) + { + Value *nsstring_value = vi->second; + + GlobalVariable *nsstring_global = dyn_cast(nsstring_value); + + if (!nsstring_global) + { + if (log) + log->PutCString("NSString variable is not a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); + + return false; + } + + if (!nsstring_global->hasInitializer()) + { + if (log) + log->PutCString("NSString variable does not have an initializer"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); + + return false; + } + + ConstantStruct *nsstring_struct = dyn_cast(nsstring_global->getInitializer()); + + if (!nsstring_struct) + { + if (log) + log->PutCString("NSString variable's initializer is not a ConstantStruct"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); + + return false; + } + + // We expect the following structure: + // + // struct { + // int *isa; + // int flags; + // char *str; + // long length; + // }; + + if (nsstring_struct->getNumOperands() != 4) + { + if (log) + log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); + + return false; + } + + Constant *nsstring_member = nsstring_struct->getOperand(2); + + if (!nsstring_member) + { + if (log) + log->PutCString("NSString initializer's str element was empty"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); + + return false; + } + + ConstantExpr *nsstring_expr = dyn_cast(nsstring_member); + + if (!nsstring_expr) + { + if (log) + log->PutCString("NSString initializer's str element is not a ConstantExpr"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); + + return false; + } + + if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) + { + if (log) + log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); + + return false; + } + + Constant *nsstring_cstr = nsstring_expr->getOperand(0); + + GlobalVariable *cstr_global = dyn_cast(nsstring_cstr); + + if (!cstr_global) + { + if (log) + log->PutCString("NSString initializer's str element is not a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); + + return false; + } + + if (!cstr_global->hasInitializer()) + { + if (log) + log->PutCString("NSString initializer's str element does not have an initializer"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); + + return false; + } + + /* + if (!cstr_array) + { + if (log) + log->PutCString("NSString initializer's str element is not a ConstantArray"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); + + return false; + } + + if (!cstr_array->isCString()) + { + if (log) + log->PutCString("NSString initializer's str element is not a C string array"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); + + return false; + } + */ + + ConstantDataArray *cstr_array = dyn_cast(cstr_global->getInitializer()); + + if (log) + { + if (cstr_array) + log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); + else + log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); + } + + if (!cstr_array) + cstr_global = NULL; + + if (!RewriteObjCConstString(nsstring_global, cstr_global)) + { + if (log) + log->PutCString("Error rewriting the constant string"); + + // We don't print an error message here because RewriteObjCConstString has done so for us. + + return false; + } + } + } + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); + + if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) + { + GlobalVariable *gv = dyn_cast(vi->second); + + if (!gv) + { + if (log) + log->PutCString("__CFConstantStringClassReference is not a global variable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); + + return false; + } + + gv->eraseFromParent(); + + break; + } + } + + return true; +} + +static bool IsObjCSelectorRef (Value *value) +{ + GlobalVariable *global_variable = dyn_cast(value); + + if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) + return false; + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewriteObjCSelector (Instruction* selector_load) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + LoadInst *load = dyn_cast(selector_load); + + if (!load) + return false; + + // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as + // + // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; + // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; + // + // where %obj is the object pointer and %tmp is the selector. + // + // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". + // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. + + // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target + + GlobalVariable *_objc_selector_references_ = dyn_cast(load->getPointerOperand()); + + if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) + return false; + + Constant *osr_initializer = _objc_selector_references_->getInitializer(); + + ConstantExpr *osr_initializer_expr = dyn_cast(osr_initializer); + + if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) + return false; + + Value *osr_initializer_base = osr_initializer_expr->getOperand(0); + + if (!osr_initializer_base) + return false; + + // Find the string's initializer (a ConstantArray) and get the string from it + + GlobalVariable *_objc_meth_var_name_ = dyn_cast(osr_initializer_base); + + if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) + return false; + + Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); + + ConstantDataArray *omvn_initializer_array = dyn_cast(omvn_initializer); + + if (!omvn_initializer_array->isString()) + return false; + + std::string omvn_initializer_string = omvn_initializer_array->getAsString(); + + if (log) + log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); + + // Construct a call to sel_registerName + + if (!m_sel_registerName) + { + lldb::addr_t sel_registerName_addr; + + static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); + if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr)) + return false; + + if (log) + log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); + + // Build the function type: struct objc_selector *sel_registerName(uint8_t*) + + // The below code would be "more correct," but in actuality what's required is uint8_t* + //Type *sel_type = StructType::get(m_module->getContext()); + //Type *sel_ptr_type = PointerType::getUnqual(sel_type); + Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); + + Type *type_array[1]; + + type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); + + ArrayRef srN_arg_types(type_array, 1); + + llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); + + // Build the constant containing the pointer to the function + PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); + Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); + m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); + } + + Value *argument_array[1]; + + Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); + + argument_array[0] = omvn_pointer; + + ArrayRef srN_arguments(argument_array, 1); + + CallInst *srN_call = CallInst::Create(m_sel_registerName, + srN_arguments, + "sel_registerName", + selector_load); + + // Replace the load with the call in all users + + selector_load->replaceAllUsesWith(srN_call); + + selector_load->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList selector_loads; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (LoadInst *load = dyn_cast(&inst)) + if (IsObjCSelectorRef(load->getPointerOperand())) + selector_loads.push_back(&inst); + } + + InstrIterator iter; + + for (iter = selector_loads.begin(); + iter != selector_loads.end(); + ++iter) + { + if (!RewriteObjCSelector(*iter)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); + + if (log) + log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); + + return false; + } + } + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + AllocaInst *alloc = dyn_cast(persistent_alloc); + + MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); + + if (!alloc_md || !alloc_md->getNumOperands()) + return false; + + ConstantInt *constant_int = mdconst::dyn_extract(alloc_md->getOperand(0)); + + if (!constant_int) + return false; + + // We attempt to register this as a new persistent variable with the DeclMap. + + uintptr_t ptr = constant_int->getZExtValue(); + + clang::VarDecl *decl = reinterpret_cast(ptr); + + lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); + + StringRef decl_name (decl->getName()); + lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); + if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) + return false; + + GlobalVariable *persistent_global = new GlobalVariable((*m_module), + alloc->getType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, + NULL, /* no initializer */ + alloc->getName().str().c_str()); + + // What we're going to do here is make believe this was a regular old external + // variable. That means we need to make the metadata valid. + + NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); + + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(persistent_global); + values[1] = ConstantAsMetadata::get(constant_int); + + ArrayRef value_ref(values, 2); + + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + named_metadata->addOperand(persistent_global_md); + + // Now, since the variable is a pointer variable, we will drop in a load of that + // pointer variable. + + LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); + + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", + PrintValue(alloc).c_str(), + PrintValue(persistent_load).c_str()); + + alloc->replaceAllUsesWith(persistent_load); + alloc->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) +{ + if (!m_resolve_vars) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList pvar_allocs; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (AllocaInst *alloc = dyn_cast(&inst)) + { + llvm::StringRef alloc_name = alloc->getName(); + + if (alloc_name.startswith("$") && + !alloc_name.startswith("$__lldb")) + { + if (alloc_name.find_first_of("0123456789") == 1) + { + if (log) + log->Printf("Rejecting a numeric persistent variable."); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); + + return false; + } + + pvar_allocs.push_back(alloc); + } + } + } + + InstrIterator iter; + + for (iter = pvar_allocs.begin(); + iter != pvar_allocs.end(); + ++iter) + { + if (!RewritePersistentAlloc(*iter)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); + + if (log) + log->PutCString("Couldn't rewrite the creation of a persistent variable"); + + return false; + } + } + + return true; +} + +bool +IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) +{ + if (!initializer) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log && log->GetVerbose()) + log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); + + Type *initializer_type = initializer->getType(); + + if (ConstantInt *int_initializer = dyn_cast(initializer)) + { + memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); + return true; + } + else if (ConstantDataArray *array_initializer = dyn_cast(initializer)) + { + if (array_initializer->isString()) + { + std::string array_initializer_string = array_initializer->getAsString(); + memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); + } + else + { + ArrayType *array_initializer_type = array_initializer->getType(); + Type *array_element_type = array_initializer_type->getElementType(); + + size_t element_size = m_target_data->getTypeAllocSize(array_element_type); + + for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) + { + Value *operand_value = array_initializer->getOperand(i); + Constant *operand_constant = dyn_cast(operand_value); + + if (!operand_constant) + return false; + + if (!MaterializeInitializer(data + (i * element_size), operand_constant)) + return false; + } + } + return true; + } + else if (ConstantStruct *struct_initializer = dyn_cast(initializer)) + { + StructType *struct_initializer_type = struct_initializer->getType(); + const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); + + for (unsigned i = 0; + i < struct_initializer->getNumOperands(); + ++i) + { + if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) + return false; + } + return true; + } + else if (isa(initializer)) + { + memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); + return true; + } + return false; +} + +bool +IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable) +{ + if (GlobalVariable::isExternalLinkage(global_variable->getLinkage())) + return false; + + if (global_variable == m_reloc_placeholder) + return true; + + uint64_t offset = m_data_allocator.GetStream().GetSize(); + + llvm::Type *variable_type = global_variable->getType(); + + Constant *initializer = global_variable->getInitializer(); + + llvm::Type *initializer_type = initializer->getType(); + + size_t size = m_target_data->getTypeAllocSize(initializer_type); + size_t align = m_target_data->getPrefTypeAlignment(initializer_type); + + const size_t mask = (align - 1); + uint64_t aligned_offset = (offset + mask) & ~mask; + m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); + offset = aligned_offset; + + lldb_private::DataBufferHeap data(size, '\0'); + + if (initializer) + if (!MaterializeInitializer(data.GetBytes(), initializer)) + return false; + + m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize()); + + Constant *new_pointer = BuildRelocation(variable_type, offset); + + global_variable->replaceAllUsesWith(new_pointer); + + global_variable->eraseFromParent(); + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + + if (ConstantExpr *constant_expr = dyn_cast(llvm_value_ptr)) + { + switch (constant_expr->getOpcode()) + { + default: + break; + case Instruction::GetElementPtr: + case Instruction::BitCast: + Value *s = constant_expr->getOperand(0); + if (!MaybeHandleVariable(s)) + return false; + } + } + else if (GlobalVariable *global_variable = dyn_cast(llvm_value_ptr)) + { + if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) + return MaterializeInternalVariable(global_variable); + + clang::NamedDecl *named_decl = DeclForGlobal(global_variable); + + if (!named_decl) + { + if (IsObjCSelectorRef(llvm_value_ptr)) + return true; + + if (!global_variable->hasExternalLinkage()) + return true; + + if (log) + log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); + + return false; + } + + std::string name (named_decl->getName().str()); + + clang::ValueDecl *value_decl = dyn_cast(named_decl); + if (value_decl == NULL) + return false; + + lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType()); + + const Type *value_type = NULL; + + if (name[0] == '$') + { + // The $__lldb_expr_result name indicates the return value has allocated as + // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, + // accesses to this static variable need to be redirected to the result of dereferencing + // a pointer that is passed in as one of the arguments. + // + // Consequently, when reporting the size of the type, we report a pointer type pointing + // to the type of $__lldb_expr_result, not the type itself. + // + // We also do this for any user-declared persistent variables. + compiler_type = compiler_type.GetPointerType(); + value_type = PointerType::get(global_variable->getType(), 0); + } + else + { + value_type = global_variable->getType(); + } + + const uint64_t value_size = compiler_type.GetByteSize(nullptr); + lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; + + if (log) + { + log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", + name.c_str(), + lldb_private::ClangASTContext::GetQualType(compiler_type).getAsString().c_str(), + 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)) + { + if (!global_variable->hasExternalLinkage()) + return true; + else if (HandleSymbol (global_variable)) + return true; + else + return false; + } + } + else if (dyn_cast(llvm_value_ptr)) + { + if (log) + log->Printf("Function pointers aren't handled right now"); + + return false; + } + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::HandleSymbol (Value *symbol) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + lldb_private::ConstString name(symbol->getName().str().c_str()); + + lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); + + if (symbol_addr == LLDB_INVALID_ADDRESS) + { + if (log) + log->Printf ("Symbol \"%s\" had no address", name.GetCString()); + + return false; + } + + if (log) + log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + + Type *symbol_type = symbol->getType(); + + Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); + + Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); + + if (log) + log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); + + symbol->replaceAllUsesWith(symbol_addr_ptr); + + return true; +} + +bool +IRForTarget::MaybeHandleCallArguments (CallInst *Old) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + + for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); + op_index < num_ops; + ++op_index) + if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); + + return false; + } + + return true; +} + +bool +IRForTarget::HandleObjCClass(Value *classlist_reference) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + GlobalVariable *global_variable = dyn_cast(classlist_reference); + + if (!global_variable) + return false; + + Constant *initializer = global_variable->getInitializer(); + + if (!initializer) + return false; + + if (!initializer->hasName()) + return false; + + StringRef name(initializer->getName()); + lldb_private::ConstString name_cstr(name.str().c_str()); + lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); + + if (log) + log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); + + if (class_ptr == LLDB_INVALID_ADDRESS) + return false; + + if (global_variable->use_empty()) + return false; + + SmallVector load_instructions; + + for (llvm::User *u : global_variable->users()) + { + if (LoadInst *load_instruction = dyn_cast(u)) + load_instructions.push_back(load_instruction); + } + + if (load_instructions.empty()) + return false; + + Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); + + for (LoadInst *load_instruction : load_instructions) + { + Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); + + load_instruction->replaceAllUsesWith(class_bitcast); + + load_instruction->eraseFromParent(); + } + + return true; +} + +bool +IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) +{ + BasicBlock::iterator ii; + + std::vector calls_to_remove; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + CallInst *call = dyn_cast(&inst); + + // MaybeHandleCallArguments handles error reporting; we are silent here + if (!call) + continue; + + bool remove = false; + + llvm::Function *func = call->getCalledFunction(); + + if (func && func->getName() == "__cxa_atexit") + remove = true; + + llvm::Value *val = call->getCalledValue(); + + if (val && val->getName() == "__cxa_atexit") + remove = true; + + if (remove) + calls_to_remove.push_back(call); + } + + for (std::vector::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); + ci != ce; + ++ci) + { + (*ci)->eraseFromParent(); + } + + return true; +} + +bool +IRForTarget::ResolveCalls(BasicBlock &basic_block) +{ + ///////////////////////////////////////////////////////////////////////// + // Prepare the current basic block for execution in the remote process + // + + BasicBlock::iterator ii; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + CallInst *call = dyn_cast(&inst); + + // MaybeHandleCallArguments handles error reporting; we are silent here + if (call && !MaybeHandleCallArguments(call)) + return false; + } + + return true; +} + +bool +IRForTarget::ResolveExternals (Function &llvm_function) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + for (GlobalVariable &global_var : m_module->globals()) + { + std::string global_name = global_var.getName().str(); + + if (log) + log->Printf("Examining %s, DeclForGlobalValue returns %p", + global_name.c_str(), + static_cast(DeclForGlobal(&global_var))); + + if (global_name.find("OBJC_IVAR") == 0) + { + if (!HandleSymbol(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); + + return false; + } + } + else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) + { + if (!HandleObjCClass(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + + return false; + } + } + else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) + { + if (!HandleObjCClass(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + + return false; + } + } + else if (DeclForGlobal(&global_var)) + { + if (!MaybeHandleVariable (&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); + + return false; + } + } + } + + return true; +} + +bool +IRForTarget::ReplaceStrings () +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + typedef std::map OffsetsTy; + + OffsetsTy offsets; + + for (GlobalVariable &gv : m_module->globals()) + { + if (!gv.hasInitializer()) + continue; + + Constant *gc = gv.getInitializer(); + + std::string str; + + if (gc->isNullValue()) + { + Type *gc_type = gc->getType(); + + ArrayType *gc_array_type = dyn_cast(gc_type); + + if (!gc_array_type) + continue; + + Type *gc_element_type = gc_array_type->getElementType(); + + IntegerType *gc_integer_type = dyn_cast(gc_element_type); + + if (gc_integer_type->getBitWidth() != 8) + continue; + + str = ""; + } + else + { + ConstantDataArray *gc_array = dyn_cast(gc); + + if (!gc_array) + continue; + + if (!gc_array->isCString()) + continue; + + if (log) + log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str()); + + str = gc_array->getAsString(); + } + + offsets[&gv] = m_data_allocator.GetStream().GetSize(); + + m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1); + } + + Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + + for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end(); + oi != oe; + ++oi) + { + GlobalVariable *gv = oi->first; + size_t offset = oi->second; + + Constant *new_initializer = BuildRelocation(char_ptr_ty, offset); + + if (log) + log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str()); + + for (llvm::User *u : gv->users()) + { + if (log) + log->Printf("Found use %s", PrintValue(u).c_str()); + + ConstantExpr *const_expr = dyn_cast(u); + StoreInst *store_inst = dyn_cast(u); + + if (const_expr) + { + if (const_expr->getOpcode() != Instruction::GetElementPtr) + { + if (log) + log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str()); + + return false; + } + + Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType()); + Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast); + + const_expr->replaceAllUsesWith(new_gep); + } + else if (store_inst) + { + Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType()); + + store_inst->setOperand(0, bit_cast); + } + else + { + if (log) + log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str()); + + return false; + } + } + + gv->eraseFromParent(); + } + + return true; +} + +bool +IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + typedef SmallVector ConstantList; + typedef SmallVector UserList; + typedef ConstantList::iterator ConstantIterator; + typedef UserList::iterator UserIterator; + + ConstantList static_constants; + UserList static_users; + + for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end(); + ii != ie; + ++ii) + { + llvm::Instruction &inst = *ii; + + for (Value *operand_val : inst.operand_values()) + { + ConstantFP *operand_constant_fp = dyn_cast(operand_val); + + if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/) + { + static_constants.push_back(operand_val); + static_users.push_back(&*ii); + } + } + } + + ConstantIterator constant_iter; + UserIterator user_iter; + + for (constant_iter = static_constants.begin(), user_iter = static_users.begin(); + constant_iter != static_constants.end(); + ++constant_iter, ++user_iter) + { + Value *operand_val = *constant_iter; + llvm::Instruction *inst = *user_iter; + + ConstantFP *operand_constant_fp = dyn_cast(operand_val); + + if (operand_constant_fp) + { + Type *operand_type = operand_constant_fp->getType(); + + APFloat operand_apfloat = operand_constant_fp->getValueAPF(); + APInt operand_apint = operand_apfloat.bitcastToAPInt(); + + const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData(); + size_t operand_data_size = operand_apint.getBitWidth() / 8; + + if (log) + { + std::string s; + raw_string_ostream ss(s); + for (size_t index = 0; + index < operand_data_size; + ++index) + { + ss << (uint32_t)operand_raw_data[index]; + ss << " "; + } + ss.flush(); + + log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str()); + } + + lldb_private::DataBufferHeap data(operand_data_size, 0); + + if (lldb_private::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder()) + { + uint8_t *data_bytes = data.GetBytes(); + + for (size_t index = 0; + index < operand_data_size; + ++index) + { + data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)]; + } + } + else + { + memcpy(data.GetBytes(), operand_raw_data, operand_data_size); + } + + uint64_t offset = m_data_allocator.GetStream().GetSize(); + + size_t align = m_target_data->getPrefTypeAlignment(operand_type); + + const size_t mask = (align - 1); + uint64_t aligned_offset = (offset + mask) & ~mask; + m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); + + m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size); + + llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo(); + + Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset); + + llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst); + + operand_constant_fp->replaceAllUsesWith(fp_load); + } + } + + return true; +} + +static bool isGuardVariableRef(Value *V) +{ + Constant *Old = NULL; + + if (!(Old = dyn_cast(V))) + return false; + + ConstantExpr *CE = NULL; + + if ((CE = dyn_cast(V))) + { + if (CE->getOpcode() != Instruction::BitCast) + return false; + + Old = CE->getOperand(0); + } + + GlobalVariable *GV = dyn_cast(Old); + + if (!GV || !GV->hasName() || + (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable + !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable + { + return false; + } + + return true; +} + +void +IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) +{ + Constant *zero(Constant::getNullValue(guard_load->getType())); + guard_load->replaceAllUsesWith(zero); + guard_load->eraseFromParent(); +} + +static void ExciseGuardStore(Instruction* guard_store) +{ + guard_store->eraseFromParent(); +} + +bool +IRForTarget::RemoveGuards(BasicBlock &basic_block) +{ + /////////////////////////////////////////////////////// + // Eliminate any reference to guard variables found. + // + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList guard_loads; + InstrList guard_stores; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (LoadInst *load = dyn_cast(&inst)) + if (isGuardVariableRef(load->getPointerOperand())) + guard_loads.push_back(&inst); + + if (StoreInst *store = dyn_cast(&inst)) + if (isGuardVariableRef(store->getPointerOperand())) + guard_stores.push_back(&inst); + } + + InstrIterator iter; + + for (iter = guard_loads.begin(); + iter != guard_loads.end(); + ++iter) + TurnGuardLoadIntoZero(*iter); + + for (iter = guard_stores.begin(); + iter != guard_stores.end(); + ++iter) + ExciseGuardStore(*iter); + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::UnfoldConstant(Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SmallVector users; + + // We do this because the use list might change, invalidating our iterator. + // Much better to keep a work list ourselves. + for (llvm::User *u : old_constant->users()) + users.push_back(u); + + for (size_t i = 0; + i < users.size(); + ++i) + { + User *user = users[i]; + + if (Constant *constant = dyn_cast(user)) + { + // synthesize a new non-constant equivalent of the constant + + if (ConstantExpr *constant_expr = dyn_cast(constant)) + { + switch (constant_expr->getOpcode()) + { + default: + if (log) + log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); + return false; + case Instruction::BitCast: + { + FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { + // UnaryExpr + // OperandList[0] is value + + if (constant_expr->getOperand(0) != old_constant) + return constant_expr; + + return new BitCastInst(value_maker.GetValue(function), + constant_expr->getType(), + "", + llvm::cast(entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder)) + return false; + } + break; + case Instruction::GetElementPtr: + { + // GetElementPtrConstantExpr + // OperandList[0] is base + // OperandList[1]... are indices + + FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { + Value *ptr = constant_expr->getOperand(0); + + if (ptr == old_constant) + ptr = value_maker.GetValue(function); + + std::vector index_vector; + + unsigned operand_index; + unsigned num_operands = constant_expr->getNumOperands(); + + for (operand_index = 1; + operand_index < num_operands; + ++operand_index) + { + Value *operand = constant_expr->getOperand(operand_index); + + if (operand == old_constant) + operand = value_maker.GetValue(function); + + index_vector.push_back(operand); + } + + ArrayRef indices(index_vector); + + return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast(entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) + return false; + } + break; + } + } + else + { + if (log) + log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); + return false; + } + } + else + { + if (Instruction *inst = llvm::dyn_cast(user)) + { + inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); + } + else + { + if (log) + log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); + return false; + } + } + } + + if (!isa(old_constant)) + { + old_constant->destroyConstant(); + } + + return true; +} + +bool +IRForTarget::ReplaceVariables (Function &llvm_function) +{ + if (!m_resolve_vars) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_decl_map->DoStructLayout(); + + if (log) + log->Printf("Element arrangement:"); + + uint32_t num_elements; + uint32_t element_index; + + size_t size; + lldb::offset_t alignment; + + if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) + return false; + + Function::arg_iterator iter(llvm_function.getArgumentList().begin()); + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); + + return false; + } + + Argument *argument = &*iter; + + if (argument->getName().equals("this")) + { + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); + + return false; + } + + argument = &*iter; + } + else if (argument->getName().equals("self")) + { + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); + + return false; + } + + if (!iter->getName().equals("_cmd")) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); + + return false; + } + + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); + + return false; + } + + argument = &*iter; + } + + if (!argument->getName().equals("$__lldb_arg")) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); + + return false; + } + + if (log) + log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); + + if (!FirstEntryInstruction) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); + + return false; + } + + LLVMContext &context(m_module->getContext()); + IntegerType *offset_type(Type::getInt32Ty(context)); + + if (!offset_type) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); + + return false; + } + + for (element_index = 0; element_index < num_elements; ++element_index) + { + const clang::NamedDecl *decl = NULL; + Value *value = NULL; + lldb::offset_t offset; + lldb_private::ConstString name; + + if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete"); + + return false; + } + + if (log) + log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, + name.GetCString(), + decl->getNameAsString().c_str(), + offset); + + if (value) + { + if (log) + log->Printf(" Replacing [%s]", PrintValue(value).c_str()); + + FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { + // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result + // variable is an rvalue, we have to synthesize a dereference of the appropriate structure + // entry in order to produce the static variable that the AST thinks it is accessing. + + llvm::Instruction *entry_instruction = llvm::cast(m_entry_instruction_finder.GetValue(function)); + + ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); + GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, + argument, + offset_int, + "", + entry_instruction); + + if (name == m_result_name && !m_result_is_pointer) + { + BitCastInst *bit_cast = new BitCastInst(get_element_ptr, + value->getType()->getPointerTo(), + "", + entry_instruction); + + LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); + + return load; + } + else + { + BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); + + return bit_cast; + } + }); + + if (Constant *constant = dyn_cast(value)) + { + UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder); + } + else if (Instruction *instruction = dyn_cast(value)) + { + value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); + } + else + { + if (log) + log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); + return false; + } + + if (GlobalVariable *var = dyn_cast(value)) + var->eraseFromParent(); + } + } + + if (log) + log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); + + return true; +} + +llvm::Constant * +IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) +{ + llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); + + llvm::Constant *offset_array[1]; + + offset_array[0] = offset_int; + + llvm::ArrayRef offsets(offset_array, 1); + llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); + llvm::Type *char_pointer_type = char_type->getPointerTo(); + + llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); + llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); + llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); + + return reloc_bitcast; +} + +bool +IRForTarget::CompleteDataAllocation () +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_data_allocator.GetStream().GetSize()) + return true; + + lldb::addr_t allocation = m_data_allocator.Allocate(); + + if (log) + { + if (allocation) + log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation); + else + log->Printf("Failed to allocate static data"); + } + + if (!allocation || allocation == LLDB_INVALID_ADDRESS) + return false; + + Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation); + Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext())); + + m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast); + + m_reloc_placeholder->eraseFromParent(); + + return true; +} + +bool +IRForTarget::StripAllGVs (Module &llvm_module) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + std::vector global_vars; + std::seterased_vars; + + bool erased = true; + + while (erased) + { + erased = false; + + for (GlobalVariable &global_var : llvm_module.globals()) + { + global_var.removeDeadConstantUsers(); + + if (global_var.use_empty()) + { + if (log) + log->Printf("Did remove %s", + PrintValue(&global_var).c_str()); + global_var.eraseFromParent(); + erased = true; + break; + } + } + } + + for (GlobalVariable &global_var : llvm_module.globals()) + { + GlobalValue::user_iterator ui = global_var.user_begin(); + + if (log) + log->Printf("Couldn't remove %s because of %s", + PrintValue(&global_var).c_str(), + PrintValue(*ui).c_str()); + } + + return true; +} + +bool +IRForTarget::runOnModule (Module &llvm_module) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_module = &llvm_module; + m_target_data.reset(new DataLayout(m_module)); + m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); + + if (log) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); + } + + Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str())); + + if (!main_function) + { + if (log) + log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); + + return false; + } + + if (!FixFunctionLinkage (*main_function)) + { + if (log) + log->Printf("Couldn't fix the linkage for the function"); + + return false; + } + + llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); + + m_reloc_placeholder = new llvm::GlobalVariable((*m_module), + int8_ty, + false /* IsConstant */, + GlobalVariable::InternalLinkage, + Constant::getNullValue(int8_ty), + "reloc_placeholder", + NULL /* InsertBefore */, + GlobalVariable::NotThreadLocal /* ThreadLocal */, + 0 /* AddressSpace */); + + //////////////////////////////////////////////////////////// + // Replace $__lldb_expr_result with a persistent variable + // + + if (!CreateResultVariable(*main_function)) + { + if (log) + log->Printf("CreateResultVariable() failed"); + + // CreateResultVariable() reports its own errors, so we don't do so here + + return false; + } + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + if (function->begin() == function->end()) + continue; + + Function::iterator bbi; + + for (bbi = function->begin(); + bbi != function->end(); + ++bbi) + { + if (!RemoveGuards(*bbi)) + { + if (log) + log->Printf("RemoveGuards() failed"); + + // RemoveGuards() reports its own errors, so we don't do so here + + return false; + } + + if (!RewritePersistentAllocs(*bbi)) + { + if (log) + log->Printf("RewritePersistentAllocs() failed"); + + // RewritePersistentAllocs() reports its own errors, so we don't do so here + + return false; + } + + if (!RemoveCXAAtExit(*bbi)) + { + if (log) + log->Printf("RemoveCXAAtExit() failed"); + + // RemoveCXAAtExit() reports its own errors, so we don't do so here + + return false; + } + } + } + + /////////////////////////////////////////////////////////////////////////////// + // Fix all Objective-C constant strings to use NSStringWithCString:encoding: + // + + if (!RewriteObjCConstStrings()) + { + if (log) + log->Printf("RewriteObjCConstStrings() failed"); + + // RewriteObjCConstStrings() reports its own errors, so we don't do so here + + return false; + } + + /////////////////////////////// + // Resolve function pointers + // + + if (!ResolveFunctionPointers(llvm_module)) + { + if (log) + log->Printf("ResolveFunctionPointers() failed"); + + // ResolveFunctionPointers() reports its own errors, so we don't do so here + + return false; + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); + bbi != bbe; + ++bbi) + { + if (!RewriteObjCSelectors(*bbi)) + { + if (log) + log->Printf("RewriteObjCSelectors() failed"); + + // RewriteObjCSelectors() reports its own errors, so we don't do so here + + return false; + } + } + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); + bbi != bbe; + ++bbi) + { + if (!ResolveCalls(*bbi)) + { + if (log) + log->Printf("ResolveCalls() failed"); + + // ResolveCalls() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceStaticLiterals(*bbi)) + { + if (log) + log->Printf("ReplaceStaticLiterals() failed"); + + return false; + } + } + } + + //////////////////////////////////////////////////////////////////////// + // Run function-level passes that only make sense on the main function + // + + if (!ResolveExternals(*main_function)) + { + if (log) + log->Printf("ResolveExternals() failed"); + + // ResolveExternals() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceVariables(*main_function)) + { + if (log) + log->Printf("ReplaceVariables() failed"); + + // ReplaceVariables() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceStrings()) + { + if (log) + log->Printf("ReplaceStrings() failed"); + + return false; + } + + if (!CompleteDataAllocation()) + { + if (log) + log->Printf("CompleteDataAllocation() failed"); + + return false; + } + + if (!StripAllGVs(llvm_module)) + { + if (log) + log->Printf("StripAllGVs() failed"); + } + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); + } + + return true; +} + +void +IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) +{ +} + +PassManagerType +IRForTarget::getPotentialPassManagerType() const +{ + return PMT_ModulePassManager; +} diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h new file mode 100644 index 000000000000..fb4abcc103de --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -0,0 +1,745 @@ +//===-- IRForTarget.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_IRForTarget_h_ +#define liblldb_IRForTarget_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/Pass.h" + +#include +#include + +namespace llvm { + class BasicBlock; + class CallInst; + class Constant; + class ConstantInt; + class Function; + class GlobalValue; + class GlobalVariable; + class Instruction; + class IntegerType; + class Module; + class StoreInst; + class DataLayout; + class Type; + class Value; +} + +namespace lldb_private { + class ClangExpressionDeclMap; + class IRExecutionUnit; + class IRMemoryMap; +} + +//---------------------------------------------------------------------- +/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" +/// @brief Transforms the IR for a function to run in the target +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRForTarget makes the second possible, by applying a series of +/// transformations to the IR which make it relocatable. These +/// transformations are discussed in more detail next to their relevant +/// functions. +//---------------------------------------------------------------------- +class IRForTarget : public llvm::ModulePass +{ +public: + enum class LookupResult { + Success, + Fail, + Ignore + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals and allocating the argument + /// struct. See the documentation for ClangExpressionDeclMap. + /// + /// @param[in] resolve_vars + /// True if the external variable references (including persistent + /// variables) should be resolved. If not, only external functions + /// are resolved. + /// + /// @param[in] execution_policy + /// Determines whether an IR interpreter can be used to statically + /// evaluate the expression. + /// + /// @param[in] const_result + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. + /// + /// @param[in] execution_unit + /// The holder for raw data associated with the expression. + /// + /// @param[in] error_stream + /// If non-NULL, a stream on which errors can be printed. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + //------------------------------------------------------------------ + IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~IRForTarget() override; + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// Implementation of the llvm::ModulePass::runOnModule() function. + /// + /// @param[in] llvm_module + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + runOnModule(llvm::Module &llvm_module) override; + + //------------------------------------------------------------------ + /// Interface stub + /// + /// Implementation of the llvm::ModulePass::assignPassManager() + /// function. + //------------------------------------------------------------------ + void + assignPassManager(llvm::PMStack &pass_mgr_stack, + llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override; + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + /// + /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() + /// function. + //------------------------------------------------------------------ + llvm::PassManagerType + getPotentialPassManagerType() const override; + +private: + //------------------------------------------------------------------ + /// Ensures that the current function's linkage is set to external. + /// Otherwise the JIT may not return an address for it. + /// + /// @param[in] llvm_function + /// The function whose linkage is to be fixed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + FixFunctionLinkage (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to replace all function pointers with their + /// integer equivalents. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + HasSideEffects (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A function-level pass to check whether the function has side + /// effects. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Get the address of a function, and a location to put the complete + /// Value of the function if one is available. + /// + /// @param[in] function + /// The function to find the location of. + /// + /// @param[out] ptr + /// The location of the function in the target. + /// + /// @param[out] name + /// The resolved name of the function (matters for intrinsics). + /// + /// @param[out] value_ptr + /// A variable to put the function's completed Value* in, or NULL + /// if the Value* shouldn't be stored anywhere. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + LookupResult + GetFunctionAddress (llvm::Function *function, + uint64_t &ptr, + lldb_private::ConstString &name, + llvm::Constant **&value_ptr); + + //------------------------------------------------------------------ + /// Build a function pointer given a type and a raw pointer. + /// + /// @param[in] type + /// The type of the function pointer to be built. + /// + /// @param[in] ptr + /// The value of the pointer. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + llvm::Constant * + BuildFunctionPointer (llvm::Type *type, + uint64_t ptr); + + void + RegisterFunctionMetadata (llvm::LLVMContext &context, + llvm::Value *function_ptr, + const char *name); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True if the function has side effects (or if this cannot + /// be determined); false otherwise. + //------------------------------------------------------------------ + bool + ResolveFunctionPointers (llvm::Module &llvm_module); + + //------------------------------------------------------------------ + /// A function-level pass to take the generated global value + /// $__lldb_expr_result and make it into a persistent variable. + /// Also see ASTResultSynthesizer. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Find the NamedDecl corresponding to a Value. This interface is + /// exposed for the IR interpreter. + /// + /// @param[in] module + /// The module containing metadata to search + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ +public: + static clang::NamedDecl * + DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); +private: + clang::NamedDecl * + DeclForGlobal (llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// + /// @param[in] initializer + /// The constant initializer for the variable. + /// + /// @param[in] name + /// The name of the result variable. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetConstantResult (llvm::Constant *initializer, + const lldb_private::ConstString &name, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetCastResult (lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CreateResultVariable (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to find Objective-C constant strings and + /// transform them to calls to CFStringCreateWithBytes. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a single Objective-C constant string. + /// + /// @param[in] NSStr + /// The constant NSString to be transformed + /// + /// @param[in] CStr + /// The constant C string inside the NSString. This will be + /// passed as the bytes argument to CFStringCreateWithBytes. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstString (llvm::GlobalVariable *NSStr, + llvm::GlobalVariable *CStr); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all Objective-C method calls and + /// rewrite them to use sel_registerName instead of statically allocated + /// selectors. The reason is that the selectors are created on the + /// assumption that the Objective-C runtime will scan the appropriate + /// section and prepare them. This doesn't happen when code is copied + /// into the target, though, and there's no easy way to induce the + /// runtime to scan them. So instead we get our selectors from + /// sel_registerName. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Replace a single selector reference + /// + /// @param[in] selector_load + /// The load of the statically-allocated selector. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelector (llvm::Instruction* selector_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelectors (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all newly-declared persistent + /// variables and register them with the ClangExprDeclMap. This + /// allows them to be materialized and dematerialized like normal + /// external variables. Before transformation, these persistent + /// variables look like normal locals, so they have an allocation. + /// This pass excises these allocations and makes references look + /// like external references where they will be resolved -- like all + /// other external references -- by ResolveExternals(). + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Handle a single allocation of a persistent variable + /// + /// @param[in] persistent_alloc + /// The allocation of the persistent variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewritePersistentAlloc (llvm::Instruction *persistent_alloc); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + //------------------------------------------------------------------ + bool + RewritePersistentAllocs (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to find all external variables and functions + /// used in the IR. Each found external variable is added to the + /// struct, and each external function is resolved in place, its call + /// replaced with a call to a function pointer whose value is the + /// address of the function in the target process. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Write an initializer to a memory array of assumed sufficient + /// size. + /// + /// @param[in] data + /// A pointer to the data to write to. + /// + /// @param[in] initializer + /// The initializer itself. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); + + //------------------------------------------------------------------ + /// Move an internal variable into the static allocation section. + /// + /// @param[in] global_variable + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInternalVariable (llvm::GlobalVariable *global_variable); + + //------------------------------------------------------------------ + /// Handle a single externally-defined variable + /// + /// @param[in] value + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleVariable (llvm::Value *value); + + //------------------------------------------------------------------ + /// Handle a single externally-defined symbol + /// + /// @param[in] symbol + /// The symbol. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleSymbol (llvm::Value *symbol); + + //------------------------------------------------------------------ + /// Handle a single externally-defined Objective-C class + /// + /// @param[in] classlist_reference + /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" + /// where n (if present) is an index. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleObjCClass(llvm::Value *classlist_reference); + + //------------------------------------------------------------------ + /// Handle all the arguments to a function call + /// + /// @param[in] C + /// The call instruction. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleCallArguments (llvm::CallInst *call_inst); + + //------------------------------------------------------------------ + /// Resolve variable references in calls to external functions + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveCalls (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// Remove calls to __cxa_atexit, which should never be generated by + /// expressions. + /// + /// @param[in] call_inst + /// The call instruction. + /// + /// @return + /// True if the scan was successful; false if some operation + /// failed + //------------------------------------------------------------------ + bool + RemoveCXAAtExit (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveExternals (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A basic block-level pass to excise guard variables from the code. + /// The result for the function is passed through Clang as a static + /// variable. Static variables normally have guard variables to + /// ensure that they are only initialized once. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a load to a guard variable to return constant 0. + /// + /// @param[in] guard_load + /// The load instruction to zero out. + //------------------------------------------------------------------ + void + TurnGuardLoadIntoZero(llvm::Instruction* guard_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RemoveGuards (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A module-level pass to allocate all string literals in a separate + /// allocation and redirect references to them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all literals that will be + /// allocated as statics by the JIT (in contrast to the Strings, + /// which already are statics) and synthesize loads for them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStaticLiterals (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to make all external variable references + /// point at the correct offsets from the void* passed into the + /// function. ClangExpressionDeclMap::DoStructLayout() must be called + /// beforehand, so that the offsets are valid. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceVariables (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to remove all global variables from the + /// module since it no longer should export or import any symbols. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + StripAllGVs (llvm::Module &llvm_module); + + class StaticDataAllocator { + public: + StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); + lldb_private::StreamString &GetStream() + { + return m_stream_string; + } + lldb::addr_t Allocate(); + + lldb::TargetSP + GetTarget(); + private: + lldb_private::IRExecutionUnit &m_execution_unit; + lldb_private::StreamString m_stream_string; + lldb::addr_t m_allocation; + }; + + /// Flags + bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved + std::string m_func_name; ///< The name of the function to translate + lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) + lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. + llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. + std::unique_ptr m_target_data; ///< The target data for the module being processed, or NULL if there is no module. + lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls + StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings + llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type + llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type + llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. + lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed + + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. + bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) + + llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. + + //------------------------------------------------------------------ + /// UnfoldConstant operates on a constant [Old] which has just been + /// replaced with a value [New]. We assume that new_value has + /// been properly placed early in the function, in front of the + /// first instruction in the entry basic block + /// [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old + /// in those uses with New. Where those uses are constants, the + /// function generates new instructions to compute the result of the + /// new, non-constant expression and places them before + /// FirstEntryInstruction. These instructions replace the constant + /// uses, so UnfoldConstant calls itself recursively for those. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + + class FunctionValueCache { + public: + typedef std::function Maker; + + FunctionValueCache (Maker const &maker); + ~FunctionValueCache (); + llvm::Value *GetValue (llvm::Function *function); + private: + Maker const m_maker; + typedef std::map FunctionValueMap; + FunctionValueMap m_values; + }; + + FunctionValueCache m_entry_instruction_finder; + + static bool + UnfoldConstant (llvm::Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder); + + //------------------------------------------------------------------ + /// Construct a reference to m_reloc_placeholder with a given type + /// and offset. This typically happens after inserting data into + /// m_data_allocator. + /// + /// @param[in] type + /// The type of the value being loaded. + /// + /// @param[in] offset + /// The offset of the value from the base of m_data_allocator. + /// + /// @return + /// The Constant for the reference, usually a ConstantExpr. + //------------------------------------------------------------------ + llvm::Constant * + BuildRelocation(llvm::Type *type, + uint64_t offset); + + //------------------------------------------------------------------ + /// Commit the allocation in m_data_allocator and use its final + /// location to replace m_reloc_placeholder. + /// + /// @param[in] module + /// The module that m_data_allocator resides in + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CompleteDataAllocation (); + +}; + +#endif // liblldb_IRForTarget_h_ diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h new file mode 100644 index 000000000000..6d51240eab5c --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoAST.h @@ -0,0 +1,3225 @@ +//===-- 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 + { + 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 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 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 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 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 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 m_len_up; + std::unique_ptr 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(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(rhs)); + } + + bool + GetDefine() const + { + return m_define; + } + void + SetDefine(bool define) + { + m_define = define; + } + + private: + friend class GoASTNode; + std::vector > m_lhs; + std::vector > 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 m_x_up; + std::unique_ptr 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(list)); + } + + private: + friend class GoASTNode; + std::vector > 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 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(args)); + } + + bool + GetEllipsis() const + { + return m_ellipsis; + } + void + SetEllipsis(bool ellipsis) + { + m_ellipsis = ellipsis; + } + + private: + friend class GoASTNode; + std::unique_ptr m_fun_up; + std::vector > 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(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(body)); + } + + private: + friend class GoASTNode; + std::vector > m_list; + std::vector > 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 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(body)); + } + + private: + friend class GoASTNode; + std::unique_ptr m_comm_up; + std::vector > 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(elts)); + } + + private: + friend class GoASTNode; + std::unique_ptr m_type_up; + std::vector > 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 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 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 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 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(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 > m_names; + std::unique_ptr m_type_up; + std::unique_ptr 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(list)); + } + + private: + friend class GoASTNode; + std::vector > 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 m_init_up; + std::unique_ptr m_cond_up; + std::unique_ptr m_post_up; + std::unique_ptr 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 m_params_up; + std::unique_ptr 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 m_recv_up; + std::unique_ptr m_name_up; + std::unique_ptr m_type_up; + std::unique_ptr 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 m_type_up; + std::unique_ptr 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(specs)); + } + + private: + friend class GoASTNode; + TokenType m_tok; + std::vector > 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 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 m_init_up; + std::unique_ptr m_cond_up; + std::unique_ptr m_body_up; + std::unique_ptr 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 m_name_up; + std::unique_ptr 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 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 m_x_up; + std::unique_ptr 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 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 m_key_up; + std::unique_ptr 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 m_label_up; + std::unique_ptr 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 m_key_up; + std::unique_ptr 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 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 m_key_up; + std::unique_ptr m_value_up; + bool m_define; + std::unique_ptr m_x_up; + std::unique_ptr 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(results)); + } + + private: + friend class GoASTNode; + std::vector > 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 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 m_x_up; + std::unique_ptr 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 m_chan_up; + std::unique_ptr 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 m_x_up; + std::unique_ptr m_low_up; + std::unique_ptr m_high_up; + std::unique_ptr 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 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 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 m_init_up; + std::unique_ptr m_tag_up; + std::unique_ptr 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 m_x_up; + std::unique_ptr 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 m_name_up; + std::unique_ptr 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 m_init_up; + std::unique_ptr m_assign_up; + std::unique_ptr 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 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(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(values)); + } + + private: + friend class GoASTNode; + std::vector > m_names; + std::unique_ptr m_type_up; + std::vector > m_values; + + GoASTValueSpec(const GoASTValueSpec &) = delete; + const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete; +}; + + +template +R GoASTDecl::Visit(V* v) const +{ + switch(GetKind()) + { + case eBadDecl: + return v->VisitBadDecl(llvm::cast(this)); + case eFuncDecl: + return v->VisitFuncDecl(llvm::cast(this)); + case eGenDecl: + return v->VisitGenDecl(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTExpr::Visit(V* v) const +{ + switch(GetKind()) + { + case eArrayType: + return v->VisitArrayType(llvm::cast(this)); + case eBadExpr: + return v->VisitBadExpr(llvm::cast(this)); + case eBasicLit: + return v->VisitBasicLit(llvm::cast(this)); + case eBinaryExpr: + return v->VisitBinaryExpr(llvm::cast(this)); + case eIdent: + return v->VisitIdent(llvm::cast(this)); + case eCallExpr: + return v->VisitCallExpr(llvm::cast(this)); + case eChanType: + return v->VisitChanType(llvm::cast(this)); + case eCompositeLit: + return v->VisitCompositeLit(llvm::cast(this)); + case eEllipsis: + return v->VisitEllipsis(llvm::cast(this)); + case eFuncType: + return v->VisitFuncType(llvm::cast(this)); + case eFuncLit: + return v->VisitFuncLit(llvm::cast(this)); + case eIndexExpr: + return v->VisitIndexExpr(llvm::cast(this)); + case eInterfaceType: + return v->VisitInterfaceType(llvm::cast(this)); + case eKeyValueExpr: + return v->VisitKeyValueExpr(llvm::cast(this)); + case eMapType: + return v->VisitMapType(llvm::cast(this)); + case eParenExpr: + return v->VisitParenExpr(llvm::cast(this)); + case eSelectorExpr: + return v->VisitSelectorExpr(llvm::cast(this)); + case eSliceExpr: + return v->VisitSliceExpr(llvm::cast(this)); + case eStarExpr: + return v->VisitStarExpr(llvm::cast(this)); + case eStructType: + return v->VisitStructType(llvm::cast(this)); + case eTypeAssertExpr: + return v->VisitTypeAssertExpr(llvm::cast(this)); + case eUnaryExpr: + return v->VisitUnaryExpr(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTSpec::Visit(V* v) const +{ + switch(GetKind()) + { + case eImportSpec: + return v->VisitImportSpec(llvm::cast(this)); + case eTypeSpec: + return v->VisitTypeSpec(llvm::cast(this)); + case eValueSpec: + return v->VisitValueSpec(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTStmt::Visit(V* v) const +{ + switch(GetKind()) + { + case eAssignStmt: + return v->VisitAssignStmt(llvm::cast(this)); + case eBadStmt: + return v->VisitBadStmt(llvm::cast(this)); + case eBlockStmt: + return v->VisitBlockStmt(llvm::cast(this)); + case eBranchStmt: + return v->VisitBranchStmt(llvm::cast(this)); + case eCaseClause: + return v->VisitCaseClause(llvm::cast(this)); + case eCommClause: + return v->VisitCommClause(llvm::cast(this)); + case eDeclStmt: + return v->VisitDeclStmt(llvm::cast(this)); + case eDeferStmt: + return v->VisitDeferStmt(llvm::cast(this)); + case eEmptyStmt: + return v->VisitEmptyStmt(llvm::cast(this)); + case eExprStmt: + return v->VisitExprStmt(llvm::cast(this)); + case eForStmt: + return v->VisitForStmt(llvm::cast(this)); + case eGoStmt: + return v->VisitGoStmt(llvm::cast(this)); + case eIfStmt: + return v->VisitIfStmt(llvm::cast(this)); + case eIncDecStmt: + return v->VisitIncDecStmt(llvm::cast(this)); + case eLabeledStmt: + return v->VisitLabeledStmt(llvm::cast(this)); + case eRangeStmt: + return v->VisitRangeStmt(llvm::cast(this)); + case eReturnStmt: + return v->VisitReturnStmt(llvm::cast(this)); + case eSelectStmt: + return v->VisitSelectStmt(llvm::cast(this)); + case eSendStmt: + return v->VisitSendStmt(llvm::cast(this)); + case eSwitchStmt: + return v->VisitSwitchStmt(llvm::cast(this)); + case eTypeSwitchStmt: + return v->VisitTypeSwitchStmt(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +void GoASTNode::WalkChildren(V &v) +{ + switch (m_kind) + { + + + case eArrayType: + { + GoASTArrayType *n = llvm::cast(this); + (void)n; + v(n->m_len_up.get()); + v(n->m_elt_up.get()); + return; + } + case eAssignStmt: + { + GoASTAssignStmt *n = llvm::cast(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(this); + (void)n; + return; + } + case eBinaryExpr: + { + GoASTBinaryExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_y_up.get()); + return; + } + case eBlockStmt: + { + GoASTBlockStmt *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_list) { v(e.get()); } + return; + } + case eIdent: + { + GoASTIdent *n = llvm::cast(this); + (void)n; + return; + } + case eBranchStmt: + { + GoASTBranchStmt *n = llvm::cast(this); + (void)n; + v(n->m_label_up.get()); + return; + } + case eCallExpr: + { + GoASTCallExpr *n = llvm::cast(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(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(this); + (void)n; + v(n->m_value_up.get()); + return; + } + case eCommClause: + { + GoASTCommClause *n = llvm::cast(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(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(this); + (void)n; + v(n->m_decl_up.get()); + return; + } + case eDeferStmt: + { + GoASTDeferStmt *n = llvm::cast(this); + (void)n; + v(n->m_call_up.get()); + return; + } + case eEllipsis: + { + GoASTEllipsis *n = llvm::cast(this); + (void)n; + v(n->m_elt_up.get()); + return; + } + case eExprStmt: + { + GoASTExprStmt *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eField: + { + GoASTField *n = llvm::cast(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(this); + (void)n; + for (auto& e : n->m_list) { v(e.get()); } + return; + } + case eForStmt: + { + GoASTForStmt *n = llvm::cast(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(this); + (void)n; + v(n->m_params_up.get()); + v(n->m_results_up.get()); + return; + } + case eFuncDecl: + { + GoASTFuncDecl *n = llvm::cast(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(this); + (void)n; + v(n->m_type_up.get()); + v(n->m_body_up.get()); + return; + } + case eGenDecl: + { + GoASTGenDecl *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_specs) { v(e.get()); } + return; + } + case eGoStmt: + { + GoASTGoStmt *n = llvm::cast(this); + (void)n; + v(n->m_call_up.get()); + return; + } + case eIfStmt: + { + GoASTIfStmt *n = llvm::cast(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(this); + (void)n; + v(n->m_name_up.get()); + v(n->m_path_up.get()); + return; + } + case eIncDecStmt: + { + GoASTIncDecStmt *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eIndexExpr: + { + GoASTIndexExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_index_up.get()); + return; + } + case eInterfaceType: + { + GoASTInterfaceType *n = llvm::cast(this); + (void)n; + v(n->m_methods_up.get()); + return; + } + case eKeyValueExpr: + { + GoASTKeyValueExpr *n = llvm::cast(this); + (void)n; + v(n->m_key_up.get()); + v(n->m_value_up.get()); + return; + } + case eLabeledStmt: + { + GoASTLabeledStmt *n = llvm::cast(this); + (void)n; + v(n->m_label_up.get()); + v(n->m_stmt_up.get()); + return; + } + case eMapType: + { + GoASTMapType *n = llvm::cast(this); + (void)n; + v(n->m_key_up.get()); + v(n->m_value_up.get()); + return; + } + case eParenExpr: + { + GoASTParenExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eRangeStmt: + { + GoASTRangeStmt *n = llvm::cast(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(this); + (void)n; + for (auto& e : n->m_results) { v(e.get()); } + return; + } + case eSelectStmt: + { + GoASTSelectStmt *n = llvm::cast(this); + (void)n; + v(n->m_body_up.get()); + return; + } + case eSelectorExpr: + { + GoASTSelectorExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_sel_up.get()); + return; + } + case eSendStmt: + { + GoASTSendStmt *n = llvm::cast(this); + (void)n; + v(n->m_chan_up.get()); + v(n->m_value_up.get()); + return; + } + case eSliceExpr: + { + GoASTSliceExpr *n = llvm::cast(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(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eStructType: + { + GoASTStructType *n = llvm::cast(this); + (void)n; + v(n->m_fields_up.get()); + return; + } + case eSwitchStmt: + { + GoASTSwitchStmt *n = llvm::cast(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(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_type_up.get()); + return; + } + case eTypeSpec: + { + GoASTTypeSpec *n = llvm::cast(this); + (void)n; + v(n->m_name_up.get()); + v(n->m_type_up.get()); + return; + } + case eTypeSwitchStmt: + { + GoASTTypeSwitchStmt *n = llvm::cast(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(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eValueSpec: + { + GoASTValueSpec *n = llvm::cast(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 new file mode 100644 index 000000000000..6de0f5619ca8 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.cpp @@ -0,0 +1,402 @@ +//===-- 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 + +#include "GoLexer.h" + +using namespace lldb_private; + +llvm::StringMap *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::InitKeywords() +{ + auto &result = *new llvm::StringMap(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 new file mode 100644 index 000000000000..e8e1635bab77 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.h @@ -0,0 +1,201 @@ +//===-- 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/StringRef.h" +#include "llvm/ADT/StringMap.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 *InitKeywords(); + + static llvm::StringMap *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 new file mode 100644 index 000000000000..0f136f7e61dc --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp @@ -0,0 +1,1035 @@ +//===-- 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 + +#include "GoParser.h" + +#include "lldb/Core/Error.h" +#include "llvm/ADT/SmallString.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" + +using namespace lldb_private; +using namespace lldb; + +namespace +{ +llvm::StringRef +DescribeToken(GoLexer::TokenType t) +{ + switch (t) + { + case GoLexer::TOK_EOF: + return ""; + 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_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> lhs; + for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) + lhs.push_back(std::unique_ptr(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 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(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 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 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 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 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 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 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 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) + return r.error(); + lit->SetType(type); + return lit; +} + +GoASTCompositeLit * +GoParser::LiteralValue() +{ + if (!match(GoLexer::OP_LBRACE)) + return nullptr; + std::unique_ptr 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 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 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()) + { + 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); + 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 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 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 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 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 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 methods(new GoASTFieldList); + while (true) + { + Rule r("MethodSpec", this); + // ( identifier Signature | TypeName ) ; + std::unique_ptr 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 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 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(Error &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 = ""; + 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 new file mode 100644 index 000000000000..9ceb670ccd11 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.h @@ -0,0 +1,165 @@ +//===-- 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 "lldb/lldb-private.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" +#include "Plugins/ExpressionParser/Go/GoLexer.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(Error &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 m_tokens; + size_t m_pos; + llvm::StringRef m_error; + llvm::StringRef m_last; + GoLexer::TokenType m_last_tok; + llvm::StringMap m_strings; + bool m_failed; +}; +} + +#endif diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp new file mode 100644 index 000000000000..3f12a2b6255b --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -0,0 +1,756 @@ +//===-- 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 +#if HAVE_SYS_TYPES_H +#include +#endif + +// C++ Includes +#include +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" + +// Project includes +#include "GoUserExpression.h" + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataEncoder.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/GoASTContext.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 "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); + + Error & + 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; + Error m_error; + llvm::StringRef m_package; + std::vector> m_statements; +}; + +VariableSP +FindGlobalVariable(TargetSP target, llvm::Twine name) +{ + ConstString fullname(name.str()); + VariableList variable_list; + const bool append = true; + if (!target) + { + return nullptr; + } + const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 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; + uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list); + if (num_matches > 0) + { + return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); + } + return CompilerType(); +} + +GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, + const EvaluateExpressionOptions &options) + : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options) +{ +} + +bool +GoUserExpression::Parse(Stream &error_stream, 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]) + error_stream.Printf("error: %s\n", error_cstr); + else + error_stream.Printf("error: expression can't be interpreted or run\n"); + return false; +} + +lldb::ExpressionResults +GoUserExpression::Execute(Stream &error_stream, 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 =="); + + error_stream.Printf("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); + Error err = m_interpreter->error(); + m_interpreter.reset(); + + if (!result_val_sp) + { + const char *error_cstr = err.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf("error: %s\n", error_cstr); + else + error_stream.Printf("error: expression can't be interpreted or run\n"); + 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()); + pv->AddVariable(result); + } + return lldb::eExpressionCompleted; +} + +bool +GoUserExpression::GoInterpreter::Parse() +{ + for (std::unique_ptr 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 &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(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(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(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("Invaild 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("Invaild 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("Invaild 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(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(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(intvalue)); + DataExtractor data(buf, order, addr_size); + + CompilerType type = LookupType(target, ConstString("int64")); + return ValueObject::CreateValueObjectFromData(nullptr, 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(nullptr, 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(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(e)) + { + std::string package; + if (auto *pkg_node = llvm::dyn_cast(sel->GetX())) + { + package = pkg_node->GetName().m_value.str(); + } + else if (auto *str_node = llvm::dyn_cast(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(e)) + { + CompilerType elem = EvaluateType(star->GetX()); + return elem.GetPointerType(); + } + if (auto *paren = llvm::dyn_cast(e)) + return EvaluateType(paren->GetX()); + if (auto *array = llvm::dyn_cast(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) +{ +} + +ConstString +GoPersistentExpressionState::GetNextPersistentVariableName() +{ + char name_cstr[256]; + // We can't use the same variable format as clang. + ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++); + ConstString name(name_cstr); + return name; +} + +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 new file mode 100644 index 000000000000..b429c68f023d --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -0,0 +1,98 @@ +//===-- 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 + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ +class GoParser; + +class GoPersistentExpressionState : public PersistentExpressionState +{ + public: + GoPersistentExpressionState(); + + ConstString GetNextPersistentVariableName() override; + + 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" +/// @brief 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, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); + + bool + Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, bool generate_debug_info) override; + + lldb::ExpressionResults + Execute(Stream &error_stream, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; + + bool + CanInterpret() override + { + return true; + } + bool + FinalizeJITExecution(Stream &error_stream, 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; + } + + private: + class GoInterpreter; + std::unique_ptr 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 new file mode 100644 index 000000000000..05b589a9976c --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/gen_go_ast.py @@ -0,0 +1,356 @@ +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 >' % 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(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 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 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 +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(this));""" % {'n':subtype} + + print """ default: + assert(false && "Invalid kind"); + } +}""" + +print """ +template +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 95ae549e0e4b..d646d4d4754a 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -290,9 +290,8 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber () const { - if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android) + if (m_arch.GetTriple().isAndroid()) return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - bool is_apple = false; if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) is_apple = true; @@ -301,6 +300,8 @@ EmulateInstructionARM::GetFramePointerRegisterNumber () const case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: is_apple = true; break; default: @@ -387,9 +388,8 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc } #endif - bool conditional = false; bool success = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -442,10 +442,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc uint32_t i; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo reg_info; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -511,8 +508,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -574,10 +570,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco uint32_t i, data; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterLoad; - else - context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.type = EmulateInstruction::eContextPopRegisterOffStack; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -586,7 +579,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco { if (BitIsSet (registers, i)) { - context.SetRegisterPlusOffset (sp_reg, addr - sp); + context.SetAddress(addr); data = MemARead(context, addr, 4, 0, &success); if (!success) return false; @@ -900,12 +893,12 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // d = UInt(Rd); setflags = (S == 1); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); + // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); Rd = Bits32 (opcode, 15, 12); setflags = BitIsSet (opcode, 20); imm32 = ARMExpandImm_C (opcode, APSR_C, carry); - // if Rd == 1111 && S == 1 then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if ((Rd == 15) && setflags) return EmulateSUBSPcLrEtc (opcode, encoding); @@ -1971,9 +1964,8 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding } #endif - bool conditional = false; bool success = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2018,10 +2010,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding addr = sp; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo sp_reg; RegisterInfo dwarf_reg; @@ -2082,8 +2071,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en #endif bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2125,10 +2113,8 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en uint32_t i; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; + RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -2178,8 +2164,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc #endif bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2222,17 +2207,15 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc uint64_t data; // uint64_t to accommodate 64-bit registers. EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterLoad; - else - context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.type = EmulateInstruction::eContextPopRegisterOffStack; + RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); for (i=0; i= 2 then SEE PUSH; + // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH; if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) { // See Push @@ -4801,7 +4781,11 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding address = base_address; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + RegisterInfo base_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); @@ -4829,8 +4813,12 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding // if wback then R[n] = offset_addr; if (wback) { - context.type = eContextRegisterLoad; + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; context.SetAddress (offset_addr); + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) return false; } @@ -9579,7 +9567,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding if ConditionPassed() then EncodingSpecificOperations(); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1); + (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); // setflags is always FALSE here else @@ -9604,7 +9592,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == 1); + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 11, 8); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); @@ -9622,12 +9610,12 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == 1); + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 15, 12); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); - // if Rd == 1111 && S == 1 then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if (d == 15 && setflags) EmulateSUBSPcLrEtc (opcode, encoding); @@ -9648,7 +9636,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding if (!success) return false; - // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1); + // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); uint32_t sp_val = ReadCoreReg (SP_REG, &success); if (!success) return false; @@ -9679,7 +9667,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod EncodingSpecificOperations(); shift_n = UInt(R[s]<7:0>); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(R[n], shifted, 0); + (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); R[d] = result; if setflags then APSR.N = result<31>; @@ -9708,7 +9696,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod m = Bits32 (opcode, 3, 0); s = Bits32 (opcode, 11, 8); - // setflags = (S == 1); shift_t = DecodeRegShift(type); + // setflags = (S == '1'); shift_t = DecodeRegShift(type); setflags = BitIsSet (opcode, 20); shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); @@ -9737,7 +9725,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod if (!success) return false; - // (result, carry, overflow) = AddWithCarry(R[n], shifted, 0); + // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); uint32_t Rn = ReadCoreReg (n, &success); if (!success) return false; @@ -9776,7 +9764,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e if ConditionPassed() then EncodingSpecificOperations(); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1); + (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); // setflags is always FALSE here else @@ -9839,14 +9827,14 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e break; case eEncodingA1: - // if Rn == 1101 then SEE SUB (SP minus register); - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == 1); + // if Rn == '1101' then SEE SUB (SP minus register); + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); - // if Rd == 1111 && S == 1 then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if ((d == 15) && setflags) EmulateSUBSPcLrEtc (opcode, encoding); @@ -9868,7 +9856,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e if (!success) return false; - // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1); + // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); uint32_t Rn = ReadCoreReg (n, &success); if (!success) return false; @@ -9929,7 +9917,7 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en switch (encoding) { case eEncodingT1: - // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:00, 32); + // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = Bits32 (opcode, 11, 8); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); @@ -10037,13 +10025,13 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi switch (encoding) { case eEncodingA1: - // if P == 0 && W == 1 then SEE STRBT; + // if P == '0' && W == '1' then SEE STRBT; // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 11, 0); - // index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10135,14 +10123,14 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin switch (encoding) { case eEncodingA1: - // if P == 0 && W == 1 then SEE STRT; - // if Rn == 1101 && P == 1 && U == 0 && W == 1 && imm12 == 000000000100 then SEE PUSH; + // if P == '0' && W == '1' then SEE STRT; + // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 11, 0); - // index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10247,15 +10235,15 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc switch (encoding) { case eEncodingT1: - //if P == 0 && W == 0 then SEE Related encodings; - //if Rn == 1111 then SEE LDRD (literal); - //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:00, 32); + //if P == '0' && W == '0' then SEE 'Related encodings'; + //if Rn == '1111' then SEE LDRD (literal); + //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); t = Bits32 (opcode, 15, 12); t2 = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - //index = (P == 1); add = (U == 1); wback = (W == 1); + //index = (P == '1'); add = (U == '1'); wback = (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); @@ -10271,8 +10259,8 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc break; case eEncodingA1: - //if Rn == 1111 then SEE LDRD (literal); - //if Rt<0> == 1 then UNPREDICTABLE; + //if Rn == '1111' then SEE LDRD (literal); + //if Rt<0> == '1' then UNPREDICTABLE; //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10281,12 +10269,12 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc n = Bits32 (opcode, 19, 16); imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - //index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - //if P == 0 && W == 1 then UNPREDICTABLE; + //if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10327,8 +10315,11 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); const uint32_t addr_byte_size = GetAddressByteSize(); uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); @@ -10339,8 +10330,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc return false; //R[t2] = MemA[address+4,4]; - - context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); + context.SetAddress(address + 4); data = MemARead (context, address + 4, addr_byte_size, 0, &success); if (!success) return false; @@ -10392,7 +10382,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco switch (encoding) { case eEncodingA1: - // if Rt<0> == 1 then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10401,12 +10391,12 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); - // index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == 0 && W == 1 then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10454,8 +10444,11 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco address = Rn; EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); // R[t] = MemA[address,4]; const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10519,14 +10512,14 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingT1: - // if P == 0 && W == 0 then SEE Related encodings; - // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:00, 32); + // if P == '0' && W == '0' then SEE 'Related encodings'; + // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); t = Bits32 (opcode, 15, 12); t2 = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // index = (P == 1); add = (U == 1); wback = (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); @@ -10542,7 +10535,7 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // if Rt<0> == 1 then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10552,12 +10545,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding n = Bits32 (opcode, 19, 16); imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - // index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == 0 && W == 1 then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10605,7 +10598,10 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding return false; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10627,9 +10623,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding //if wback then R[n] = offset_addr; if (wback) { - context.type = eContextAdjustBaseRegister; + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; context.SetAddress (offset_addr); - + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) return false; } @@ -10667,7 +10666,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingA1: - // if Rt<0> == 1 then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10677,12 +10676,12 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); - // index = (P == 1); add = (U == 1); wback = (P == 0) || (W == 1); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == 0 && W == 1 then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10737,7 +10736,11 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding return false; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (t == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); @@ -10808,25 +10811,25 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc { case eEncodingT1: case eEncodingA1: - // if P == 0 && U == 0 && W == 0 then SEE Related encodings; - // if P == 0 && U == 1 && W == 1 && Rn == 1101 then SEE VPOP; - // if P == 1 && W == 0 then SEE VLDR; - // if P == U && W == 1 then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == 1); wback = (W == 1); + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); single_regs = false; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:00, 32); + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see FLDMX. + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. regs = Bits32 (opcode, 7, 0) / 2; // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -10841,22 +10844,22 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc case eEncodingT2: case eEncodingA2: - // if P == 0 && U == 0 && W == 0 then SEE Related encodings; - // if P == 0 && U == 1 && W == 1 && Rn == 1101 then SEE VPOP; - // if P == 1 && W == 0 then SEE VLDR; - // if P == U && W == 1 then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == 1); wback = (W == 1); d = UInt(Vd:D); n = UInt(Rn); + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); single_regs = true; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); n = Bits32 (opcode, 19, 16); - // imm32 = ZeroExtend(imm8:00, 32); regs = UInt(imm8); + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); imm32 = Bits32 (opcode, 7, 0) << 2; regs = Bits32 (opcode, 7, 0); @@ -11000,25 +11003,25 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc { case eEncodingT1: case eEncodingA1: - // if P == 0 && U == 0 && W == 0 then SEE Related encodings; - // if P == 1 && U == 0 && W == 1 && Rn == 1101 then SEE VPUSH; - // if P == 1 && W == 0 then SEE VSTR; - // if P == U && W == 1 then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == 1); wback = (W == 1); + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); single_regs = false; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:00, 32); + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see FSTMX. + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. regs = Bits32 (opcode, 7, 0) / 2; // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -11033,22 +11036,22 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc case eEncodingT2: case eEncodingA2: - // if P == 0 && U == 0 && W == 0 then SEE Related encodings; - // if P == 1 && U == 0 && W == 1 && Rn == 1101 then SEE VPUSH; - // if P == 1 && W == 0 then SEE VSTR; - // if P == U && W == 1 then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == 1); wback = (W == 1); d = UInt(Vd:D); n = UInt(Rn); + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); single_regs = true; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); n = Bits32 (opcode, 19, 16); - // imm32 = ZeroExtend(imm8:00, 32); regs = UInt(imm8); + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); imm32 = Bits32 (opcode, 7, 0) << 2; regs = Bits32 (opcode, 7, 0); @@ -11193,7 +11196,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) { case eEncodingT1: case eEncodingA1: - // single_reg = FALSE; add = (U == 1); imm32 = ZeroExtend(imm8:00, 32); + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = false; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11206,7 +11209,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) case eEncodingT2: case eEncodingA2: - // single_reg = TRUE; add = (U == 1); imm32 = ZeroExtend(imm8:00, 32); + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = true; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11322,7 +11325,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) { case eEncodingT1: case eEncodingA1: - // single_reg = FALSE; add = (U == 1); imm32 = ZeroExtend(imm8:00, 32); + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = false; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11339,7 +11342,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) case eEncodingT2: case eEncodingA2: - // single_reg = TRUE; add = (U == 1); imm32 = ZeroExtend(imm8:00, 32); + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = true; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11461,16 +11464,16 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e case eEncodingA1: { // case type of - // when 0111 - // regs = 1; if align<1> == 1 then UNDEFINED; - // when 1010 - // regs = 2; if align == 11 then UNDEFINED; - // when 0110 - // regs = 3; if align<1> == 1 then UNDEFINED; - // when 0010 + // when '0111' + // regs = 1; if align<1> == '1' then UNDEFINED; + // when '1010' + // regs = 2; if align == '11' then UNDEFINED; + // when '0110' + // regs = 3; if align<1> == '1' then UNDEFINED; + // when '0010' // regs = 4; // otherwise - // SEE Related encodings; + // SEE 'Related encodings'; uint32_t type = Bits32 (opcode, 11, 8); uint32_t align = Bits32 (opcode, 5, 4); if (type == 7) // '0111' @@ -11499,7 +11502,7 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e else return false; - // alignment = if align == 00 then 1 else 4 << UInt(align); + // alignment = if align == '00' then 1 else 4 << UInt(align); if (align == 0) alignment = 1; else @@ -11624,13 +11627,13 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi { uint32_t size = Bits32 (opcode, 11, 10); uint32_t index_align = Bits32 (opcode, 7, 4); - // if size == 11 then SEE VLD1 (single element to all lanes); + // if size == '11' then SEE VLD1 (single element to all lanes); if (size == 3) return EmulateVLD1SingleAll (opcode, encoding); // case size of if (size == 0) // when '00' { - // if index_align<0> != 0 then UNDEFINED; + // if index_align<0> != '0' then UNDEFINED; if (BitIsClear (index_align, 0)) return false; @@ -11640,9 +11643,9 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi index = Bits32 (index_align, 3, 1); alignment = 1; } - else if (size == 1) // when 01 + else if (size == 1) // when '01' { - // if index_align<1> != 0 then UNDEFINED; + // if index_align<1> != '0' then UNDEFINED; if (BitIsClear (index_align, 1)) return false; @@ -11651,19 +11654,19 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi esize = 16; index = Bits32 (index_align, 3, 2); - // alignment = if index_align<0> == 0 then 1 else 2; + // alignment = if index_align<0> == '0' then 1 else 2; if (BitIsClear (index_align, 0)) alignment = 1; else alignment = 2; } - else if (size == 2) // when 10 + else if (size == 2) // when '10' { - // if index_align<2> != 0 then UNDEFINED; + // if index_align<2> != '0' then UNDEFINED; if (BitIsClear (index_align, 2)) return false; - // if index_align<1:0> != 00 && index_align<1:0> != 11 then UNDEFINED; + // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) return false; @@ -11672,7 +11675,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi esize = 32; index = Bit32 (index_align, 3); - // alignment = if index_align<1:0> == 00 then 1 else 4; + // alignment = if index_align<1:0> == '00' then 1 else 4; if (Bits32 (index_align, 1, 0) == 0) alignment = 1; else @@ -11806,35 +11809,35 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e uint32_t align = Bits32 (opcode, 5, 4); // case type of - if (type == 7) // when 0111 + if (type == 7) // when '0111' { - // regs = 1; if align<1> == 1 then UNDEFINED; + // regs = 1; if align<1> == '1' then UNDEFINED; regs = 1; if (BitIsSet (align, 1)) return false; } - else if (type == 10) // when 1010 + else if (type == 10) // when '1010' { - // regs = 2; if align == 11 then UNDEFINED; + // regs = 2; if align == '11' then UNDEFINED; regs = 2; if (align == 3) return false; } - else if (type == 6) // when 0110 + else if (type == 6) // when '0110' { - // regs = 3; if align<1> == 1 then UNDEFINED; + // regs = 3; if align<1> == '1' then UNDEFINED; regs = 3; if (BitIsSet (align, 1)) return false; } - else if (type == 2) // when 0010 + else if (type == 2) // when '0010' // regs = 4; regs = 4; else // otherwise - // SEE Related encodings; + // SEE 'Related encodings'; return false; - // alignment = if align == 00 then 1 else 4 << UInt(align); + // alignment = if align == '00' then 1 else 4 << UInt(align); if (align == 0) alignment = 1; else @@ -11964,14 +11967,14 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc uint32_t size = Bits32 (opcode, 11, 10); uint32_t index_align = Bits32 (opcode, 7, 4); - // if size == 11 then UNDEFINED; + // if size == '11' then UNDEFINED; if (size == 3) return false; // case size of - if (size == 0) // when 00 + if (size == 0) // when '00' { - // if index_align<0> != 0 then UNDEFINED; + // if index_align<0> != '0' then UNDEFINED; if (BitIsClear (index_align, 0)) return false; // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; @@ -11980,9 +11983,9 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc index = Bits32 (index_align, 3, 1); alignment = 1; } - else if (size == 1) // when 01 + else if (size == 1) // when '01' { - // if index_align<1> != 0 then UNDEFINED; + // if index_align<1> != '0' then UNDEFINED; if (BitIsClear (index_align, 1)) return false; @@ -11991,19 +11994,19 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc esize = 16; index = Bits32 (index_align, 3, 2); - // alignment = if index_align<0> == 0 then 1 else 2; + // alignment = if index_align<0> == '0' then 1 else 2; if (BitIsClear (index_align, 0)) alignment = 1; else alignment = 2; } - else if (size == 2) // when 10 + else if (size == 2) // when '10' { - // if index_align<2> != 0 then UNDEFINED; + // if index_align<2> != '0' then UNDEFINED; if (BitIsClear (index_align, 2)) return false; - // if index_align<1:0> != 00 && index_align<1:0> != 11 then UNDEFINED; + // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) return false; @@ -12012,7 +12015,7 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc esize = 32; index = Bit32 (index_align, 3); - // alignment = if index_align<1:0> == 00 then 1 else 4; + // alignment = if index_align<1:0> == '00' then 1 else 4; if (Bits32 (index_align, 1, 0) == 0) alignment = 1; else @@ -12125,12 +12128,12 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc case eEncodingT1: case eEncodingA1: { - //if size == 11 || (size == 00 && a == 1) then UNDEFINED; + //if size == '11' || (size == '00' && a == '1') then UNDEFINED; uint32_t size = Bits32 (opcode, 7, 6); if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) return false; - //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == 0 then 1 else 2; + //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2; ebytes = 1 << size; elements = 8 / ebytes; if (BitIsClear (opcode, 5)) @@ -12138,7 +12141,7 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc else regs = 2; - //alignment = if a == 0 then 1 else ebytes; + //alignment = if a == '0' then 1 else ebytes; if (BitIsClear (opcode, 4)) alignment = 1; else @@ -12235,19 +12238,19 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod UNPREDICTABLE; operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; case opcode of - when 0000 result = R[n] AND operand2; // AND - when 0001 result = R[n] EOR operand2; // EOR - when 0010 (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1); // SUB - when 0011 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1); // RSB - when 0100 (result, -, -) = AddWithCarry(R[n], operand2, 0); // ADD - when 0101 (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC - when 0110 (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC - when 0111 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC - when 1100 result = R[n] OR operand2; // ORR - when 1101 result = operand2; // MOV - when 1110 result = R[n] AND NOT(operand2); // BIC - when 1111 result = NOT(operand2); // MVN - CPSRWriteByInstr(SPSR[], 1111, TRUE); + when '0000' result = R[n] AND operand2; // AND + when '0001' result = R[n] EOR operand2; // EOR + when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB + when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB + when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD + when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC + when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC + when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC + when '1100' result = R[n] OR operand2; // ORR + when '1101' result = operand2; // MOV + when '1110' result = R[n] AND NOT(operand2); // BIC + when '1111' result = NOT(operand2); // MVN + CPSRWriteByInstr(SPSR[], '1111', TRUE); BranchWritePC(result); #endif @@ -12267,7 +12270,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod { case eEncodingT1: // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE - // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = 0010; // = SUB + // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB n = 14; imm32 = Bits32 (opcode, 7, 0); register_form = false; @@ -12329,62 +12332,62 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod // case opcode of switch (code) { - case 0: // when 0000 + case 0: // when '0000' // result = R[n] AND operand2; // AND result.result = Rn & operand2; break; - case 1: // when 0001 + case 1: // when '0001' // result = R[n] EOR operand2; // EOR result.result = Rn ^ operand2; break; - case 2: // when 0010 - // (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1); // SUB + case 2: // when '0010' + // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB result = AddWithCarry (Rn, ~(operand2), 1); break; - case 3: // when 0011 - // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1); // RSB + case 3: // when '0011' + // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB result = AddWithCarry (~(Rn), operand2, 1); break; - case 4: // when 0100 - // (result, -, -) = AddWithCarry(R[n], operand2, 0); // ADD + case 4: // when '0100' + // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD result = AddWithCarry (Rn, operand2, 0); break; - case 5: // when 0101 + case 5: // when '0101' // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC result = AddWithCarry (Rn, operand2, APSR_C); break; - case 6: // when 0110 + case 6: // when '0110' // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC result = AddWithCarry (Rn, ~(operand2), APSR_C); break; - case 7: // when 0111 + case 7: // when '0111' // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC result = AddWithCarry (~(Rn), operand2, APSR_C); break; - case 10: // when 1100 + case 10: // when '1100' // result = R[n] OR operand2; // ORR result.result = Rn | operand2; break; - case 11: // when 1101 + case 11: // when '1101' // result = operand2; // MOV result.result = operand2; break; - case 12: // when 1110 + case 12: // when '1110' // result = R[n] AND NOT(operand2); // BIC result.result = Rn & ~(operand2); break; - case 15: // when 1111 + case 15: // when '1111' // result = NOT(operand2); // MVN result.result = ~(operand2); break; @@ -12392,7 +12395,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod default: return false; } - // CPSRWriteByInstr(SPSR[], 1111, TRUE); + // CPSRWriteByInstr(SPSR[], '1111', TRUE); // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for // the best. @@ -13076,7 +13079,7 @@ EmulateInstructionARM::ArchVersion () } bool -EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional) +EmulateInstructionARM::ConditionPassed (const uint32_t opcode) { // If we are ignoring conditions, then always return true. // this allows us to iterate over disassembly code and still @@ -13084,12 +13087,8 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio // bits set in the CPSR register... if (m_ignore_conditions) return true; - - if (is_conditional) - *is_conditional = true; const uint32_t cond = CurrentCond (opcode); - if (cond == UINT32_MAX) return false; @@ -13149,8 +13148,6 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio case 7: // Always execute (cond == 0b1110, or the special 0b1111 which gives // opcodes different meanings, but always means execution happens. - if (is_conditional) - *is_conditional = false; return true; } @@ -13642,6 +13639,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) return true; } +bool +EmulateInstructionARM::IsInstructionConditional() +{ + const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); + return cond != 0xe && cond != 0xf && cond != UINT32_MAX; +} + bool EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index d107ca6bc702..893f43f19977 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -94,20 +94,20 @@ public: return false; } - virtual lldb_private::ConstString - GetPluginName() + lldb_private::ConstString + GetPluginName() override { return GetPluginNameStatic(); } - virtual uint32_t - GetPluginVersion() + uint32_t + GetPluginVersion() override { return 1; } bool - SetTargetTriple (const ArchSpec &arch); + SetTargetTriple (const ArchSpec &arch) override; enum Mode { @@ -148,8 +148,8 @@ public: // { // } - virtual bool - SupportsEmulatingInstructionsOfType (InstructionType inst_type) + bool + SupportsEmulatingInstructionsOfType (InstructionType inst_type) override { return SupportsEmulatingInstructionsOfTypeStatic (inst_type); } @@ -157,32 +157,32 @@ public: virtual bool SetArchitecture (const ArchSpec &arch); - virtual bool - ReadInstruction (); + bool + ReadInstruction () override; - virtual bool - SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target); + bool + SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) override; - virtual bool - EvaluateInstruction (uint32_t evaluate_options); - - virtual bool - TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data); + bool + EvaluateInstruction (uint32_t evaluate_options) override; - virtual bool - GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info); - + bool + IsInstructionConditional() override; - virtual bool - CreateFunctionEntryUnwind (UnwindPlan &unwind_plan); + bool + TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; + + bool + GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) override; + + bool + CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override; uint32_t ArchVersion(); bool - ConditionPassed (const uint32_t opcode, - bool *is_conditional = NULL); // Filled in with true if the opcode is a conditional opcode - // Filled in with false if the opcode is always executed + ConditionPassed (const uint32_t opcode); uint32_t CurrentCond (const uint32_t opcode); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 992df1fba59e..372ccf9b05f4 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -231,58 +231,72 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode) //---------------------------------------------------------------------- // push register(s) - { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB , , # {, }" }, - { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS , , # {, }" }, - { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD , , # {, }" }, - { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS , , # {, }" }, - - { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB , , # {, }" }, - { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS , , # {, }" }, - { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD , , # {, }" }, - { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS , , # {, }" }, - - { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP
, , [{, #}]" }, - { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - - { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP
, , [, #]!" }, - { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - - { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP
, , [, #]!" }, - { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - - { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP
, , [{, #}]" }, - { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - - { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP
, , [, #]!" }, - { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - - { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP
, , [, #]!" }, - { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - - { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B
, , [{, #}]" }, + { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [{, #}]" }, + + { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP
, , [, #]!" }, + { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + + { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP
, , [, #]!" }, + { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + + { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [{, #}]" }, + { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + + { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [, #]!" }, + { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + + { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [, #]!" }, + { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + + { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [], #" }, + { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [], #" }, + { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [, #]!" }, + { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [, #]!" }, + { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [{, #}]" }, + { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [{, #}]" }, + + { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [], #" }, + { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [], #" }, + { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [, #]!" }, + { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [, #]!" }, + { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [{, #}]" }, + { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [{, #}]" }, + + { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B