From f6aab3d83b51b91c24247ad2c2573574de475a82 Mon Sep 17 00:00:00 2001 From: robert Date: Sat, 11 Nov 2023 18:22:53 +0000 Subject: [PATCH] import lldb from LLVM-16.0.6 --- gnu/llvm/lldb/.clang-tidy | 2 +- gnu/llvm/lldb/CMakeLists.txt | 96 +- gnu/llvm/lldb/CODE_OWNERS.txt | 9 +- gnu/llvm/lldb/bindings/CMakeLists.txt | 16 +- .../bindings/interface/SBCommandInterpreter.i | 3 + .../lldb/bindings/interface/SBCompileUnit.i | 16 + gnu/llvm/lldb/bindings/interface/SBData.i | 6 +- gnu/llvm/lldb/bindings/interface/SBDebugger.i | 28 + gnu/llvm/lldb/bindings/interface/SBFileSpec.i | 13 +- .../lldb/bindings/interface/SBInstruction.i | 3 + .../bindings/interface/SBMemoryRegionInfo.i | 3 + .../interface/SBMemoryRegionInfoList.i | 3 + gnu/llvm/lldb/bindings/interface/SBModule.i | 10 + gnu/llvm/lldb/bindings/interface/SBPlatform.i | 3 + gnu/llvm/lldb/bindings/interface/SBProcess.i | 5 +- gnu/llvm/lldb/bindings/interface/SBSection.i | 4 + gnu/llvm/lldb/bindings/interface/SBSymbol.i | 4 + .../bindings/interface/SBSymbolContextList.i | 2 +- gnu/llvm/lldb/bindings/interface/SBTarget.i | 8 +- gnu/llvm/lldb/bindings/interface/SBThread.i | 6 + gnu/llvm/lldb/bindings/interface/SBTrace.i | 4 + .../lldb/bindings/interface/SBTraceCursor.i | 58 + gnu/llvm/lldb/bindings/interface/SBType.i | 39 +- .../bindings/interface/SBTypeNameSpecifier.i | 6 + gnu/llvm/lldb/bindings/interface/SBValue.i | 3 + .../lldb/bindings/interface/SBValueList.i | 6 + gnu/llvm/lldb/bindings/interfaces.swig | 4 +- gnu/llvm/lldb/bindings/lua/CMakeLists.txt | 52 + .../lldb/bindings/lua/lua-swigsafecast.swig | 31 +- gnu/llvm/lldb/bindings/lua/lua-typemaps.swig | 238 +- gnu/llvm/lldb/bindings/lua/lua-wrapper.swig | 157 +- gnu/llvm/lldb/bindings/lua/lua.swig | 5 + gnu/llvm/lldb/bindings/macros.swig | 4 +- gnu/llvm/lldb/bindings/python/CMakeLists.txt | 58 +- .../lldb/bindings/python/createPythonInit.py | 8 + .../lldb/bindings/python/get-python-config.py | 72 + gnu/llvm/lldb/bindings/python/lldb-python | 17 + .../bindings/python/python-extensions.swig | 1 + .../bindings/python/python-swigsafecast.swig | 182 +- .../lldb/bindings/python/python-typemaps.h | 2 + .../lldb/bindings/python/python-typemaps.swig | 386 ++- .../lldb/bindings/python/python-wrapper.swig | 1849 ++++++------ gnu/llvm/lldb/bindings/python/python.swig | 12 +- .../lldb/cmake/caches/Apple-lldb-base.cmake | 1 - gnu/llvm/lldb/cmake/modules/AddLLDB.cmake | 16 +- .../lldb/cmake/modules/FindLuaAndSwig.cmake | 15 +- .../cmake/modules/FindPythonAndSwig.cmake | 12 +- gnu/llvm/lldb/cmake/modules/LLDBConfig.cmake | 65 +- .../cmake/modules/LLDBGenerateConfig.cmake | 4 +- .../lldb/cmake/modules/LLDBStandalone.cmake | 41 +- gnu/llvm/lldb/docs/conf.py | 44 +- gnu/llvm/lldb/docs/design/sbapi.rst | 2 +- gnu/llvm/lldb/docs/doxygen.cfg.in | 2 +- gnu/llvm/lldb/docs/index.rst | 16 +- gnu/llvm/lldb/docs/lldb-gdb-remote.txt | 184 +- gnu/llvm/lldb/docs/lldb-platform-packets.txt | 54 +- gnu/llvm/lldb/docs/python_api_enums.rst | 1 + gnu/llvm/lldb/docs/resources/bots.rst | 4 +- gnu/llvm/lldb/docs/resources/build.rst | 119 +- gnu/llvm/lldb/docs/resources/contributing.rst | 2 +- gnu/llvm/lldb/docs/resources/fuzzing.rst | 73 + gnu/llvm/lldb/docs/resources/test.rst | 122 +- .../docs/testsuite/a-detailed-walkthrough.txt | 67 +- gnu/llvm/lldb/docs/use/extensions.rst | 138 + gnu/llvm/lldb/docs/use/intel_pt.rst | 252 ++ gnu/llvm/lldb/docs/use/links.rst | 82 + gnu/llvm/lldb/docs/use/map.rst | 66 +- gnu/llvm/lldb/docs/use/ondemand.rst | 158 ++ gnu/llvm/lldb/docs/use/python-reference.rst | 91 +- gnu/llvm/lldb/docs/use/python.rst | 24 +- gnu/llvm/lldb/docs/use/remote.rst | 5 + gnu/llvm/lldb/docs/use/symbolication.rst | 2 +- gnu/llvm/lldb/docs/use/troubleshooting.rst | 4 +- gnu/llvm/lldb/docs/use/tutorial.rst | 6 +- gnu/llvm/lldb/docs/use/variable.rst | 176 +- .../customization/bin-utils/binutils.py | 2 - .../customization/import-python/importcmd.py | 1 - .../customization/pwd-cd-and-system/utils.py | 1 - .../lldb/examples/darwin/heap_find/heap.py | 56 +- .../python/armv7_cortex_m_target_defintion.py | 2 +- gnu/llvm/lldb/examples/python/bsd.py | 3 +- gnu/llvm/lldb/examples/python/cmdtemplate.py | 4 +- gnu/llvm/lldb/examples/python/crashlog.py | 668 +++-- gnu/llvm/lldb/examples/python/delta.py | 11 +- .../lldb/examples/python/diagnose_nsstring.py | 4 +- .../lldb/examples/python/diagnose_unwind.py | 10 +- .../lldb/examples/python/disassembly_mode.py | 2 +- .../lldb/examples/python/gdb_disassemble.py | 7 +- gnu/llvm/lldb/examples/python/gdbremote.py | 49 +- gnu/llvm/lldb/examples/python/globals.py | 1 - .../lldb/examples/python/in_call_stack.py | 2 +- gnu/llvm/lldb/examples/python/jump.py | 6 +- .../lldb/examples/python/lldb_module_utils.py | 9 +- gnu/llvm/lldb/examples/python/lldbtk.py | 1 - gnu/llvm/lldb/examples/python/mach_o.py | 1 - gnu/llvm/lldb/examples/python/memory.py | 9 +- gnu/llvm/lldb/examples/python/performance.py | 2 - .../lldb/examples/python/process_events.py | 2 - gnu/llvm/lldb/examples/python/pytracer.py | 1 - .../crashlog_scripted_process.py | 211 ++ .../scripted_process/scripted_platform.py | 96 + .../scripted_process/scripted_process.py | 295 +- .../lldb/examples/python/scripted_step.py | 2 - gnu/llvm/lldb/examples/python/shadow.py | 1 - gnu/llvm/lldb/examples/python/sources.py | 3 +- gnu/llvm/lldb/examples/python/stacks.py | 8 +- .../lldb/examples/python/step_and_print.py | 2 +- .../lldb/examples/python/symbolication.py | 3 +- gnu/llvm/lldb/examples/python/types.py | 8 +- .../lldb/examples/scripting/tree_utils.py | 2 - .../lldb/examples/summaries/cocoa/CFArray.py | 7 +- .../lldb/examples/summaries/cocoa/CFBag.py | 7 +- .../examples/summaries/cocoa/CFBinaryHeap.py | 7 +- .../examples/summaries/cocoa/CFBitVector.py | 1 - .../examples/summaries/cocoa/CFDictionary.py | 9 +- .../lldb/examples/summaries/cocoa/Logger.py | 1 - .../lldb/examples/summaries/cocoa/NSData.py | 9 +- .../examples/summaries/cocoa/NSIndexSet.py | 7 +- .../examples/summaries/cocoa/NSMachPort.py | 7 +- .../lldb/examples/summaries/cocoa/NSNumber.py | 2 - .../lldb/examples/summaries/cocoa/NSSet.py | 9 +- gnu/llvm/lldb/examples/summaries/synth.py | 3 +- .../lldb/examples/synthetic/gnu_libstdcpp.py | 456 ++- gnu/llvm/lldb/examples/synthetic/libcxx.py | 29 +- .../synthetic/recognizer_function/example.py | 63 + .../recognizer_function/lldb-commands | 7 + .../synthetic/recognizer_function/program.cpp | 114 + .../include/lldb/API/SBBreakpointLocation.h | 4 +- .../include/lldb/API/SBCommandInterpreter.h | 4 + .../lldb/include/lldb/API/SBCommunication.h | 2 +- .../lldb/include/lldb/API/SBCompileUnit.h | 3 + gnu/llvm/lldb/include/lldb/API/SBData.h | 3 + gnu/llvm/lldb/include/lldb/API/SBDebugger.h | 48 +- gnu/llvm/lldb/include/lldb/API/SBDefines.h | 13 + gnu/llvm/lldb/include/lldb/API/SBError.h | 9 +- .../include/lldb/API/SBExecutionContext.h | 2 - gnu/llvm/lldb/include/lldb/API/SBFileSpec.h | 1 + .../lldb/include/lldb/API/SBInstruction.h | 2 + .../include/lldb/API/SBMemoryRegionInfo.h | 6 + .../include/lldb/API/SBMemoryRegionInfoList.h | 3 + gnu/llvm/lldb/include/lldb/API/SBModule.h | 2 + gnu/llvm/lldb/include/lldb/API/SBPlatform.h | 2 + gnu/llvm/lldb/include/lldb/API/SBProcess.h | 16 +- gnu/llvm/lldb/include/lldb/API/SBReproducer.h | 3 - gnu/llvm/lldb/include/lldb/API/SBSection.h | 6 + .../lldb/include/lldb/API/SBStructuredData.h | 2 +- gnu/llvm/lldb/include/lldb/API/SBSymbol.h | 36 + .../lldb/include/lldb/API/SBSymbolContext.h | 4 +- gnu/llvm/lldb/include/lldb/API/SBTarget.h | 7 + gnu/llvm/lldb/include/lldb/API/SBThread.h | 2 + gnu/llvm/lldb/include/lldb/API/SBTrace.h | 43 +- .../lldb/include/lldb/API/SBTraceCursor.h | 181 ++ gnu/llvm/lldb/include/lldb/API/SBType.h | 6 +- .../include/lldb/API/SBTypeNameSpecifier.h | 5 + .../lldb/include/lldb/API/SBTypeSummary.h | 4 +- gnu/llvm/lldb/include/lldb/API/SBValue.h | 6 + gnu/llvm/lldb/include/lldb/API/SBValueList.h | 29 + .../lldb/include/lldb/Breakpoint/Breakpoint.h | 23 +- .../include/lldb/Breakpoint/BreakpointID.h | 6 +- .../include/lldb/Breakpoint/BreakpointList.h | 3 + .../lldb/Breakpoint/BreakpointLocation.h | 3 + .../lldb/Breakpoint/BreakpointLocationList.h | 3 + .../lldb/Breakpoint/BreakpointOptions.h | 9 +- .../lldb/Breakpoint/BreakpointResolver.h | 3 +- .../Breakpoint/BreakpointResolverFileLine.h | 14 +- .../Breakpoint/BreakpointResolverScripted.h | 11 +- .../lldb/include/lldb/Breakpoint/Watchpoint.h | 5 +- .../lldb/Breakpoint/WatchpointOptions.h | 2 +- gnu/llvm/lldb/include/lldb/Core/Address.h | 17 +- .../lldb/include/lldb/Core/AddressRange.h | 2 - .../lldb/include/lldb/Core/Communication.h | 245 +- .../lldb/include/lldb/Core/DataFileCache.h | 228 ++ gnu/llvm/lldb/include/lldb/Core/Debugger.h | 162 +- .../lldb/include/lldb/Core/DebuggerEvents.h | 111 + gnu/llvm/lldb/include/lldb/Core/Declaration.h | 6 +- .../lldb/include/lldb/Core/Disassembler.h | 35 +- .../include/lldb/Core/DumpDataExtractor.h | 12 +- .../include/lldb/Core/DumpRegisterValue.h | 6 +- .../include/lldb/Core/EmulateInstruction.h | 24 +- .../lldb/include/lldb/Core/FileSpecList.h | 28 +- .../lldb/include/lldb/Core/FormatEntity.h | 13 +- gnu/llvm/lldb/include/lldb/Core/Highlighter.h | 7 +- gnu/llvm/lldb/include/lldb/Core/IOHandler.h | 42 +- .../include/lldb/Core/LoadedModuleInfoList.h | 10 +- gnu/llvm/lldb/include/lldb/Core/Mangled.h | 87 +- gnu/llvm/lldb/include/lldb/Core/Module.h | 232 +- gnu/llvm/lldb/include/lldb/Core/ModuleList.h | 35 +- gnu/llvm/lldb/include/lldb/Core/ModuleSpec.h | 31 +- .../lldb/include/lldb/Core/PluginInterface.h | 6 +- .../lldb/include/lldb/Core/PluginManager.h | 128 +- gnu/llvm/lldb/include/lldb/Core/Progress.h | 3 +- .../include/lldb/Core/RichManglingContext.h | 38 +- gnu/llvm/lldb/include/lldb/Core/Section.h | 13 + .../include/lldb/Core/SourceLocationSpec.h | 10 +- .../lldb/include/lldb/Core/SourceManager.h | 3 +- .../include/lldb/Core/StreamAsynchronousIO.h | 2 +- .../include/lldb/Core/StructuredDataImpl.h | 9 +- .../lldb/include/lldb/Core/ThreadSafeValue.h | 3 +- .../include/lldb/Core/ThreadedCommunication.h | 288 ++ .../lldb/include/lldb/Core/UniqueCStringMap.h | 31 +- .../lldb/Core/UserSettingsController.h | 5 +- gnu/llvm/lldb/include/lldb/Core/Value.h | 8 +- gnu/llvm/lldb/include/lldb/Core/ValueObject.h | 10 +- .../lldb/include/lldb/Core/ValueObjectCast.h | 3 +- .../lldb/include/lldb/Core/ValueObjectChild.h | 7 +- .../lldb/Core/ValueObjectConstResult.h | 5 +- .../lldb/Core/ValueObjectConstResultImpl.h | 1 - .../lldb/Core/ValueObjectDynamicValue.h | 14 +- .../include/lldb/Core/ValueObjectMemory.h | 3 +- .../include/lldb/Core/ValueObjectRegister.h | 14 +- .../lldb/Core/ValueObjectSyntheticFilter.h | 3 +- .../include/lldb/Core/ValueObjectVariable.h | 3 +- gnu/llvm/lldb/include/lldb/Core/dwarf.h | 7 +- .../lldb/DataFormatters/DataVisualization.h | 2 +- .../DataFormatters/DumpValueObjectOptions.h | 3 +- .../lldb/DataFormatters/FormatClasses.h | 82 +- .../lldb/DataFormatters/FormatManager.h | 11 +- .../lldb/DataFormatters/FormattersContainer.h | 100 +- .../lldb/DataFormatters/FormattersHelpers.h | 2 +- .../lldb/DataFormatters/StringPrinter.h | 20 +- .../lldb/DataFormatters/TypeCategory.h | 409 +-- .../lldb/DataFormatters/TypeCategoryMap.h | 12 +- .../include/lldb/DataFormatters/TypeSummary.h | 2 +- .../lldb/DataFormatters/TypeSynthetic.h | 8 +- .../lldb/DataFormatters/ValueObjectPrinter.h | 2 + .../lldb/DataFormatters/VectorIterator.h | 5 +- .../include/lldb/Expression/DWARFExpression.h | 135 +- .../lldb/Expression/DWARFExpressionList.h | 150 + .../lldb/Expression/ExpressionVariable.h | 5 +- .../include/lldb/Expression/IRExecutionUnit.h | 24 +- .../include/lldb/Expression/Materializer.h | 22 + .../include/lldb/Expression/UserExpression.h | 23 +- .../lldb/include/lldb/Host/Config.h.cmake | 11 +- gnu/llvm/lldb/include/lldb/Host/Debug.h | 14 +- gnu/llvm/lldb/include/lldb/Host/Editline.h | 20 +- gnu/llvm/lldb/include/lldb/Host/File.h | 80 +- gnu/llvm/lldb/include/lldb/Host/FileSystem.h | 56 +- gnu/llvm/lldb/include/lldb/Host/Host.h | 62 +- .../lldb/include/lldb/Host/HostInfoBase.h | 8 +- .../include/lldb/Host/HostNativeProcessBase.h | 4 +- .../include/lldb/Host/HostNativeThreadBase.h | 2 +- gnu/llvm/lldb/include/lldb/Host/HostProcess.h | 4 +- gnu/llvm/lldb/include/lldb/Host/MainLoop.h | 109 +- .../lldb/include/lldb/Host/MainLoopBase.h | 39 +- .../include/lldb/Host/ProcessLaunchInfo.h | 15 +- gnu/llvm/lldb/include/lldb/Host/Socket.h | 32 +- gnu/llvm/lldb/include/lldb/Host/Terminal.h | 139 +- .../lldb/include/lldb/Host/ThreadLauncher.h | 13 +- gnu/llvm/lldb/include/lldb/Host/XML.h | 4 +- .../lldb/Host/common/NativeProcessProtocol.h | 49 +- .../lldb/Host/common/NativeRegisterContext.h | 2 +- .../lldb/Host/common/NativeThreadProtocol.h | 9 + .../lldb/Host/freebsd/HostInfoFreeBSD.h | 4 +- gnu/llvm/lldb/include/lldb/Host/linux/Host.h | 4 +- .../include/lldb/Host/linux/HostInfoLinux.h | 4 +- .../include/lldb/Host/macosx/HostInfoMacOSX.h | 6 +- .../lldb/Host/macosx/HostThreadMacOSX.h | 3 +- .../include/lldb/Host/netbsd/HostInfoNetBSD.h | 4 +- .../posix/ConnectionFileDescriptorPosix.h | 88 +- .../include/lldb/Host/posix/HostInfoPosix.h | 2 + .../lldb/Host/posix/HostProcessPosix.h | 4 +- .../include/lldb/Host/posix/MainLoopPosix.h | 99 + .../lldb/Host/windows/HostInfoWindows.h | 5 +- .../lldb/Host/windows/HostProcessWindows.h | 6 +- .../lldb/Host/windows/MainLoopWindows.h | 53 + .../lldb/include/lldb/Host/windows/PosixApi.h | 27 - .../lldb/include/lldb/Host/windows/windows.h | 3 +- .../lldb/Interpreter/CommandCompletions.h | 10 + .../include/lldb/Interpreter/CommandHistory.h | 3 +- .../lldb/Interpreter/CommandInterpreter.h | 156 +- .../include/lldb/Interpreter/CommandObject.h | 65 +- .../lldb/Interpreter/CommandObjectMultiword.h | 27 +- .../Interpreter/CommandOptionArgumentTable.h | 271 ++ .../lldb/Interpreter/CommandReturnObject.h | 11 +- .../lldb/Interpreter/OptionGroupFormat.h | 9 +- .../lldb/Interpreter/OptionGroupMemoryTag.h | 44 + .../OptionGroupValueObjectDisplay.h | 3 +- .../include/lldb/Interpreter/OptionValue.h | 12 +- .../lldb/Interpreter/OptionValueArray.h | 4 +- .../lldb/Interpreter/OptionValueBoolean.h | 4 + .../lldb/Interpreter/OptionValueChar.h | 4 + .../lldb/Interpreter/OptionValueDictionary.h | 8 +- .../lldb/Interpreter/OptionValueFileSpec.h | 4 + .../lldb/Interpreter/OptionValueFormat.h | 2 + .../Interpreter/OptionValueFormatEntity.h | 2 + .../lldb/Interpreter/OptionValueLanguage.h | 2 + .../Interpreter/OptionValuePathMappings.h | 2 + .../lldb/Interpreter/OptionValueProperties.h | 11 +- .../lldb/Interpreter/OptionValueRegex.h | 4 + .../lldb/Interpreter/OptionValueSInt64.h | 4 + .../lldb/Interpreter/OptionValueString.h | 9 + .../lldb/Interpreter/OptionValueUInt64.h | 4 + .../lldb/Interpreter/OptionValueUUID.h | 4 + .../lldb/include/lldb/Interpreter/Options.h | 4 +- .../lldb/include/lldb/Interpreter/Property.h | 13 +- .../lldb/Interpreter/ScriptInterpreter.h | 35 +- .../lldb/Interpreter/ScriptedInterface.h | 75 + .../lldb/Interpreter/ScriptedMetadata.h | 45 + .../Interpreter/ScriptedPlatformInterface.h | 49 + .../Interpreter/ScriptedProcessInterface.h | 80 +- gnu/llvm/lldb/include/lldb/Symbol/Block.h | 2 + .../include/lldb/Symbol/CompactUnwindInfo.h | 9 +- .../lldb/include/lldb/Symbol/CompileUnit.h | 6 +- .../lldb/include/lldb/Symbol/CompilerType.h | 120 +- .../include/lldb/Symbol/DWARFCallFrameInfo.h | 8 +- .../lldb/include/lldb/Symbol/DebugMacros.h | 2 +- gnu/llvm/lldb/include/lldb/Symbol/Function.h | 24 +- gnu/llvm/lldb/include/lldb/Symbol/LineTable.h | 6 +- .../include/lldb/Symbol/LocateSymbolFile.h | 13 +- .../include/lldb/Symbol/ObjectContainer.h | 52 +- .../lldb/include/lldb/Symbol/ObjectFile.h | 77 +- gnu/llvm/lldb/include/lldb/Symbol/Symbol.h | 50 + .../lldb/include/lldb/Symbol/SymbolFile.h | 306 +- .../include/lldb/Symbol/SymbolFileOnDemand.h | 262 ++ .../lldb/include/lldb/Symbol/SymbolVendor.h | 4 +- gnu/llvm/lldb/include/lldb/Symbol/Symtab.h | 132 +- .../lldb/include/lldb/Symbol/TaggedASTType.h | 3 +- gnu/llvm/lldb/include/lldb/Symbol/Type.h | 116 +- gnu/llvm/lldb/include/lldb/Symbol/TypeList.h | 7 +- gnu/llvm/lldb/include/lldb/Symbol/TypeMap.h | 8 +- .../lldb/include/lldb/Symbol/TypeSystem.h | 89 +- .../lldb/include/lldb/Symbol/UnwindPlan.h | 8 +- .../lldb/include/lldb/Symbol/UnwindTable.h | 5 +- gnu/llvm/lldb/include/lldb/Symbol/Variable.h | 18 +- gnu/llvm/lldb/include/lldb/Target/ABI.h | 27 +- .../lldb/Target/AppleArm64ExceptionClass.def | 50 + .../lldb/Target/AppleArm64ExceptionClass.h | 50 + .../lldb/include/lldb/Target/DynamicLoader.h | 61 +- .../include/lldb/Target/DynamicRegisterInfo.h | 136 + .../lldb/Target/InstrumentationRuntime.h | 3 +- gnu/llvm/lldb/include/lldb/Target/Language.h | 51 +- .../include/lldb/Target/LanguageRuntime.h | 9 +- gnu/llvm/lldb/include/lldb/Target/Memory.h | 2 +- .../include/lldb/Target/MemoryRegionInfo.h | 36 +- .../include/lldb/Target/MemoryTagManager.h | 40 +- .../lldb/include/lldb/Target/MemoryTagMap.h | 98 + .../include/lldb/Target/PathMappingList.h | 52 +- gnu/llvm/lldb/include/lldb/Target/Platform.h | 214 +- .../include/lldb/Target/PostMortemProcess.h | 2 +- gnu/llvm/lldb/include/lldb/Target/Process.h | 334 ++- .../include/lldb/Target/ProcessStructReader.h | 5 +- .../lldb/include/lldb/Target/ProcessTrace.h | 13 +- .../include/lldb/Target/RegisterCheckpoint.h | 9 +- .../include/lldb/Target/RegisterContext.h | 6 +- .../lldb/Target/RegisterContextUnwind.h | 5 +- .../include/lldb/Target/RemoteAwarePlatform.h | 5 +- .../include/lldb/Target/SectionLoadHistory.h | 2 +- .../include/lldb/Target/SectionLoadList.h | 2 +- .../lldb/include/lldb/Target/StackFrame.h | 25 +- .../lldb/include/lldb/Target/StackFrameList.h | 3 + .../lldb/Target/StackFrameRecognizer.h | 3 +- gnu/llvm/lldb/include/lldb/Target/StackID.h | 4 +- .../lldb/include/lldb/Target/Statistics.h | 188 ++ gnu/llvm/lldb/include/lldb/Target/StopInfo.h | 12 +- .../lldb/include/lldb/Target/SystemRuntime.h | 2 +- gnu/llvm/lldb/include/lldb/Target/Target.h | 196 +- gnu/llvm/lldb/include/lldb/Target/Thread.h | 38 +- .../lldb/include/lldb/Target/ThreadPlan.h | 55 +- .../lldb/Target/ThreadPlanCallFunction.h | 4 +- .../Target/ThreadPlanCallUserExpression.h | 2 +- .../include/lldb/Target/ThreadPlanPython.h | 14 +- .../include/lldb/Target/ThreadPlanStack.h | 8 +- .../Target/ThreadPlanStepOverBreakpoint.h | 2 +- gnu/llvm/lldb/include/lldb/Target/Trace.h | 362 ++- .../lldb/include/lldb/Target/TraceCursor.h | 292 +- .../lldb/include/lldb/Target/TraceDumper.h | 433 +++ .../lldb/include/lldb/Target/TraceExporter.h | 2 + .../lldb/include/lldb/Target/UnixSignals.h | 31 +- gnu/llvm/lldb/include/lldb/Target/Unwind.h | 2 +- .../lldb/include/lldb/Target/UnwindLLDB.h | 2 +- .../lldb/include/lldb/Utility/AnsiTerminal.h | 101 +- gnu/llvm/lldb/include/lldb/Utility/Args.h | 32 +- .../lldb/include/lldb/Utility/ConstString.h | 33 +- .../lldb/include/lldb/Utility/DataBuffer.h | 104 +- .../include/lldb/Utility/DataBufferHeap.h | 28 +- .../include/lldb/Utility/DataBufferLLVM.h | 53 +- .../lldb/include/lldb/Utility/DataEncoder.h | 249 +- .../lldb/include/lldb/Utility/DataExtractor.h | 16 +- .../lldb/include/lldb/Utility/Diagnostics.h | 70 + .../lldb/include/lldb/Utility/Environment.h | 6 +- gnu/llvm/lldb/include/lldb/Utility/Event.h | 8 +- gnu/llvm/lldb/include/lldb/Utility/FileSpec.h | 85 +- .../lldb/include/lldb/Utility/GDBRemote.h | 80 +- .../include/lldb/Utility/Instrumentation.h | 103 + gnu/llvm/lldb/include/lldb/Utility/LLDBLog.h | 61 + gnu/llvm/lldb/include/lldb/Utility/Log.h | 163 +- .../lldb/include/lldb/Utility/Predicate.h | 24 +- .../lldb/include/lldb/Utility/ProcessInfo.h | 23 +- gnu/llvm/lldb/include/lldb/Utility/RangeMap.h | 89 +- .../lldb/include/lldb/Utility/RegisterValue.h | 12 +- gnu/llvm/lldb/include/lldb/Utility/Scalar.h | 2 +- .../lldb/include/lldb/Utility/SelectHelper.h | 4 +- .../lldb/include/lldb/Utility/SharedCluster.h | 23 +- gnu/llvm/lldb/include/lldb/Utility/Status.h | 20 +- .../lldb/include/lldb/Utility/StreamTee.h | 12 +- .../lldb/Utility/StringExtractorGDBRemote.h | 19 +- .../lldb/include/lldb/Utility/StringList.h | 3 + .../include/lldb/Utility/StructuredData.h | 43 +- gnu/llvm/lldb/include/lldb/Utility/Timeout.h | 14 +- gnu/llvm/lldb/include/lldb/Utility/Timer.h | 26 +- .../lldb/Utility/TraceGDBRemotePackets.h | 45 +- .../Utility/TraceIntelPTGDBRemotePackets.h | 94 +- gnu/llvm/lldb/include/lldb/Utility/UUID.h | 56 +- .../lldb/include/lldb/Utility/UriParser.h | 36 +- .../include/lldb/Utility/UserIDResolver.h | 15 +- gnu/llvm/lldb/include/lldb/Version/Version.h | 23 + .../lldb/include/lldb/Version/Version.inc.in | 6 + gnu/llvm/lldb/include/lldb/lldb-defines.h | 15 +- .../lldb/include/lldb/lldb-enumerations.h | 109 +- gnu/llvm/lldb/include/lldb/lldb-forward.h | 57 +- .../include/lldb/lldb-private-enumerations.h | 34 +- .../include/lldb/lldb-private-interfaces.h | 11 +- .../lldb/include/lldb/lldb-private-types.h | 22 +- gnu/llvm/lldb/include/lldb/lldb-private.h | 7 - gnu/llvm/lldb/include/lldb/lldb-types.h | 1 + gnu/llvm/lldb/include/lldb/module.modulemap | 5 +- .../Python/lldbsuite/support/encoded_file.py | 27 +- .../Python/lldbsuite/support/funcutils.py | 2 +- .../Python/lldbsuite/support/seven.py | 63 +- .../Python/lldbsuite/test/README-TestSuite | 30 +- .../Python/lldbsuite/test/builders/builder.py | 202 +- .../Python/lldbsuite/test/builders/darwin.py | 75 +- .../Python/lldbsuite/test/concurrent_base.py | 4 +- .../Python/lldbsuite/test/configuration.py | 26 +- .../Python/lldbsuite/test/decorators.py | 79 +- .../packages/Python/lldbsuite/test/dotest.py | 45 +- .../Python/lldbsuite/test/dotest_args.py | 17 +- .../Python/lldbsuite/test/gdbclientutils.py | 647 +++++ .../Python/lldbsuite/test/lldbbench.py | 2 +- .../Python/lldbsuite/test/lldbgdbclient.py | 102 + .../Python/lldbsuite/test/lldbinline.py | 5 +- .../Python/lldbsuite/test/lldbpexpect.py | 30 +- .../Python/lldbsuite/test/lldbplatform.py | 7 +- .../Python/lldbsuite/test/lldbplatformutil.py | 69 +- .../Python/lldbsuite/test/lldbtest.py | 526 ++-- .../Python/lldbsuite/test/lldbutil.py | 345 ++- .../Python/lldbsuite/test/make/Android.rules | 4 +- .../Python/lldbsuite/test/make/Makefile.rules | 82 +- .../Python/lldbsuite/test/make/thread.h | 4 + .../Python/lldbsuite/test/test_categories.py | 14 +- .../test/tools/intelpt/intelpt_testcase.py | 64 +- .../test/tools/lldb-server/fork_testbase.py | 207 ++ .../tools/lldb-server/gdbremote_testcase.py | 91 +- .../tools/lldb-server/lldbgdbserverutils.py | 52 +- .../tools/lldb-vscode/lldbvscode_testcase.py | 36 +- .../test/tools/lldb-vscode/vscode.py | 54 +- .../lldbsuite/test_event/build_exception.py | 9 +- gnu/llvm/lldb/source/API/CMakeLists.txt | 18 +- gnu/llvm/lldb/source/API/SBAddress.cpp | 117 +- gnu/llvm/lldb/source/API/SBAttachInfo.cpp | 133 +- gnu/llvm/lldb/source/API/SBBlock.cpp | 114 +- gnu/llvm/lldb/source/API/SBBreakpoint.cpp | 337 +-- .../lldb/source/API/SBBreakpointLocation.cpp | 194 +- gnu/llvm/lldb/source/API/SBBreakpointName.cpp | 196 +- .../source/API/SBBreakpointOptionCommon.cpp | 24 +- gnu/llvm/lldb/source/API/SBBroadcaster.cpp | 94 +- .../lldb/source/API/SBCommandInterpreter.cpp | 401 +-- .../API/SBCommandInterpreterRunOptions.cpp | 165 +- .../lldb/source/API/SBCommandReturnObject.cpp | 174 +- gnu/llvm/lldb/source/API/SBCommunication.cpp | 92 +- gnu/llvm/lldb/source/API/SBCompileUnit.cpp | 125 +- gnu/llvm/lldb/source/API/SBData.cpp | 244 +- gnu/llvm/lldb/source/API/SBDebugger.cpp | 970 +++---- gnu/llvm/lldb/source/API/SBDeclaration.cpp | 81 +- gnu/llvm/lldb/source/API/SBEnvironment.cpp | 63 +- gnu/llvm/lldb/source/API/SBError.cpp | 74 +- gnu/llvm/lldb/source/API/SBEvent.cpp | 87 +- .../lldb/source/API/SBExecutionContext.cpp | 75 +- .../lldb/source/API/SBExpressionOptions.cpp | 180 +- gnu/llvm/lldb/source/API/SBFile.cpp | 71 +- gnu/llvm/lldb/source/API/SBFileSpec.cpp | 97 +- gnu/llvm/lldb/source/API/SBFileSpecList.cpp | 64 +- gnu/llvm/lldb/source/API/SBFrame.cpp | 334 +-- gnu/llvm/lldb/source/API/SBFunction.cpp | 100 +- gnu/llvm/lldb/source/API/SBHostOS.cpp | 67 +- gnu/llvm/lldb/source/API/SBInstruction.cpp | 129 +- .../lldb/source/API/SBInstructionList.cpp | 88 +- .../lldb/source/API/SBLanguageRuntime.cpp | 23 +- gnu/llvm/lldb/source/API/SBLaunchInfo.cpp | 223 +- gnu/llvm/lldb/source/API/SBLineEntry.cpp | 85 +- gnu/llvm/lldb/source/API/SBListener.cpp | 138 +- .../lldb/source/API/SBMemoryRegionInfo.cpp | 115 +- .../source/API/SBMemoryRegionInfoList.cpp | 73 +- gnu/llvm/lldb/source/API/SBModule.cpp | 337 +-- gnu/llvm/lldb/source/API/SBModuleSpec.cpp | 157 +- gnu/llvm/lldb/source/API/SBPlatform.cpp | 433 +-- gnu/llvm/lldb/source/API/SBProcess.cpp | 474 +--- gnu/llvm/lldb/source/API/SBProcessInfo.cpp | 80 +- gnu/llvm/lldb/source/API/SBQueue.cpp | 86 +- gnu/llvm/lldb/source/API/SBQueueItem.cpp | 56 +- gnu/llvm/lldb/source/API/SBReproducer.cpp | 282 +- gnu/llvm/lldb/source/API/SBSection.cpp | 124 +- gnu/llvm/lldb/source/API/SBSourceManager.cpp | 61 +- gnu/llvm/lldb/source/API/SBStream.cpp | 56 +- gnu/llvm/lldb/source/API/SBStringList.cpp | 66 +- gnu/llvm/lldb/source/API/SBStructuredData.cpp | 120 +- gnu/llvm/lldb/source/API/SBSymbol.cpp | 104 +- gnu/llvm/lldb/source/API/SBSymbolContext.cpp | 133 +- .../lldb/source/API/SBSymbolContextList.cpp | 71 +- gnu/llvm/lldb/source/API/SBTarget.cpp | 1102 +++----- gnu/llvm/lldb/source/API/SBThread.cpp | 366 +-- .../lldb/source/API/SBThreadCollection.cpp | 47 +- gnu/llvm/lldb/source/API/SBThreadPlan.cpp | 219 +- gnu/llvm/lldb/source/API/SBTrace.cpp | 110 +- gnu/llvm/lldb/source/API/SBTraceCursor.cpp | 137 + gnu/llvm/lldb/source/API/SBType.cpp | 466 ++-- gnu/llvm/lldb/source/API/SBTypeCategory.cpp | 382 +-- gnu/llvm/lldb/source/API/SBTypeEnumMember.cpp | 102 +- gnu/llvm/lldb/source/API/SBTypeFilter.cpp | 83 +- gnu/llvm/lldb/source/API/SBTypeFormat.cpp | 77 +- .../lldb/source/API/SBTypeNameSpecifier.cpp | 110 +- gnu/llvm/lldb/source/API/SBTypeSummary.cpp | 192 +- gnu/llvm/lldb/source/API/SBTypeSynthetic.cpp | 102 +- gnu/llvm/lldb/source/API/SBUnixSignals.cpp | 82 +- gnu/llvm/lldb/source/API/SBValue.cpp | 467 +--- gnu/llvm/lldb/source/API/SBValueList.cpp | 91 +- .../lldb/source/API/SBVariablesOptions.cpp | 98 +- gnu/llvm/lldb/source/API/SBWatchpoint.cpp | 124 +- .../lldb/source/API/SystemInitializerFull.cpp | 12 +- .../lldb/source/API/liblldb-private.exports | 1 + gnu/llvm/lldb/source/API/liblldb.exports | 1 + .../lldb/source/Breakpoint/Breakpoint.cpp | 88 +- .../lldb/source/Breakpoint/BreakpointID.cpp | 22 +- .../source/Breakpoint/BreakpointIDList.cpp | 12 +- .../lldb/source/Breakpoint/BreakpointList.cpp | 15 +- .../source/Breakpoint/BreakpointLocation.cpp | 10 +- .../BreakpointLocationCollection.cpp | 10 +- .../Breakpoint/BreakpointLocationList.cpp | 11 +- .../source/Breakpoint/BreakpointOptions.cpp | 30 +- .../source/Breakpoint/BreakpointResolver.cpp | 22 +- .../Breakpoint/BreakpointResolverAddress.cpp | 10 +- .../Breakpoint/BreakpointResolverFileLine.cpp | 133 +- .../BreakpointResolverFileRegex.cpp | 4 +- .../Breakpoint/BreakpointResolverName.cpp | 27 +- .../Breakpoint/BreakpointResolverScripted.cpp | 33 +- .../lldb/source/Breakpoint/BreakpointSite.cpp | 6 +- .../source/Breakpoint/BreakpointSiteList.cpp | 2 +- .../Breakpoint/StoppointCallbackContext.cpp | 2 +- .../lldb/source/Breakpoint/Watchpoint.cpp | 20 +- .../lldb/source/Breakpoint/WatchpointList.cpp | 2 +- .../source/Breakpoint/WatchpointOptions.cpp | 6 +- gnu/llvm/lldb/source/CMakeLists.txt | 41 +- gnu/llvm/lldb/source/Commands/CMakeLists.txt | 6 +- .../source/Commands/CommandCompletions.cpp | 71 +- .../source/Commands/CommandObjectApropos.cpp | 4 +- .../Commands/CommandObjectBreakpoint.cpp | 207 +- .../CommandObjectBreakpointCommand.cpp | 44 +- .../source/Commands/CommandObjectCommands.cpp | 682 ++++- .../Commands/CommandObjectDWIMPrint.cpp | 80 + .../source/Commands/CommandObjectDWIMPrint.h | 40 + .../Commands/CommandObjectDiagnostics.cpp | 114 + .../Commands/CommandObjectDiagnostics.h | 29 + .../Commands/CommandObjectDisassemble.cpp | 74 +- .../Commands/CommandObjectDisassemble.h | 1 + .../Commands/CommandObjectExpression.cpp | 60 +- .../source/Commands/CommandObjectFrame.cpp | 153 +- .../lldb/source/Commands/CommandObjectGUI.cpp | 26 +- .../source/Commands/CommandObjectHelp.cpp | 15 +- .../lldb/source/Commands/CommandObjectHelp.h | 2 +- .../lldb/source/Commands/CommandObjectLog.cpp | 158 +- .../source/Commands/CommandObjectMemory.cpp | 343 ++- .../Commands/CommandObjectMemoryTag.cpp | 33 +- .../Commands/CommandObjectMultiword.cpp | 186 +- .../source/Commands/CommandObjectPlatform.cpp | 442 ++- .../source/Commands/CommandObjectProcess.cpp | 557 +++- .../source/Commands/CommandObjectQuit.cpp | 5 +- .../Commands/CommandObjectRegexCommand.cpp | 72 +- .../Commands/CommandObjectRegexCommand.h | 5 + .../source/Commands/CommandObjectRegister.cpp | 12 +- .../source/Commands/CommandObjectScript.cpp | 25 +- .../source/Commands/CommandObjectScript.h | 2 +- .../source/Commands/CommandObjectSession.cpp | 9 +- .../source/Commands/CommandObjectSettings.cpp | 40 +- .../source/Commands/CommandObjectSource.cpp | 65 +- .../source/Commands/CommandObjectStats.cpp | 75 +- .../source/Commands/CommandObjectTarget.cpp | 765 +++-- .../source/Commands/CommandObjectThread.cpp | 616 ++-- .../Commands/CommandObjectThreadUtil.cpp | 15 +- .../source/Commands/CommandObjectThreadUtil.h | 4 +- .../source/Commands/CommandObjectTrace.cpp | 189 +- .../source/Commands/CommandObjectType.cpp | 521 ++-- .../source/Commands/CommandObjectVersion.cpp | 10 +- .../Commands/CommandObjectWatchpoint.cpp | 41 +- .../CommandObjectWatchpointCommand.cpp | 38 +- .../Commands/CommandOptionArgumentTable.cpp | 313 +++ .../Commands/CommandOptionsProcessLaunch.cpp | 4 +- .../Commands/CommandOptionsProcessLaunch.h | 2 +- gnu/llvm/lldb/source/Commands/Options.td | 232 +- gnu/llvm/lldb/source/Commands/OptionsBase.td | 6 +- gnu/llvm/lldb/source/Core/Address.cpp | 76 +- gnu/llvm/lldb/source/Core/AddressRange.cpp | 19 +- .../source/Core/AddressResolverFileLine.cpp | 8 +- gnu/llvm/lldb/source/Core/CMakeLists.txt | 8 +- gnu/llvm/lldb/source/Core/Communication.cpp | 309 +-- gnu/llvm/lldb/source/Core/CoreProperties.td | 67 +- gnu/llvm/lldb/source/Core/DataFileCache.cpp | 322 +++ gnu/llvm/lldb/source/Core/Debugger.cpp | 536 +++- gnu/llvm/lldb/source/Core/DebuggerEvents.cpp | 120 + gnu/llvm/lldb/source/Core/Disassembler.cpp | 57 +- .../lldb/source/Core/DumpDataExtractor.cpp | 282 +- .../lldb/source/Core/DumpRegisterValue.cpp | 105 +- gnu/llvm/lldb/source/Core/DynamicLoader.cpp | 162 +- .../lldb/source/Core/EmulateInstruction.cpp | 77 +- gnu/llvm/lldb/source/Core/FileSpecList.cpp | 53 +- gnu/llvm/lldb/source/Core/Highlighter.cpp | 5 +- gnu/llvm/lldb/source/Core/IOHandler.cpp | 104 +- .../lldb/source/Core/IOHandlerCursesGUI.cpp | 2225 ++++++++++++--- gnu/llvm/lldb/source/Core/Mangled.cpp | 229 +- gnu/llvm/lldb/source/Core/Module.cpp | 471 ++-- gnu/llvm/lldb/source/Core/ModuleList.cpp | 204 +- gnu/llvm/lldb/source/Core/PluginManager.cpp | 329 ++- .../lldb/source/Core/RichManglingContext.cpp | 73 +- gnu/llvm/lldb/source/Core/Section.cpp | 104 +- .../lldb/source/Core/SourceLocationSpec.cpp | 13 +- gnu/llvm/lldb/source/Core/SourceManager.cpp | 39 +- .../lldb/source/Core/StreamAsynchronousIO.cpp | 5 +- gnu/llvm/lldb/source/Core/StreamFile.cpp | 7 +- .../source/Core/ThreadedCommunication.cpp | 371 +++ .../source/Core/UserSettingsController.cpp | 17 +- gnu/llvm/lldb/source/Core/Value.cpp | 19 +- gnu/llvm/lldb/source/Core/ValueObject.cpp | 67 +- gnu/llvm/lldb/source/Core/ValueObjectCast.cpp | 3 +- .../lldb/source/Core/ValueObjectChild.cpp | 14 +- .../source/Core/ValueObjectConstResult.cpp | 3 +- .../Core/ValueObjectConstResultImpl.cpp | 17 +- .../source/Core/ValueObjectDynamicValue.cpp | 11 +- .../lldb/source/Core/ValueObjectMemory.cpp | 6 +- .../lldb/source/Core/ValueObjectRegister.cpp | 74 +- .../Core/ValueObjectSyntheticFilter.cpp | 11 +- .../lldb/source/Core/ValueObjectVariable.cpp | 24 +- .../DataFormatters/CXXFunctionPointer.cpp | 31 +- .../DataFormatters/DataVisualization.cpp | 10 +- .../DataFormatters/DumpValueObjectOptions.cpp | 3 +- .../source/DataFormatters/FormatManager.cpp | 115 +- .../DataFormatters/FormattersHelpers.cpp | 75 +- .../source/DataFormatters/StringPrinter.cpp | 24 +- .../source/DataFormatters/TypeCategory.cpp | 320 +-- .../source/DataFormatters/TypeCategoryMap.cpp | 11 +- .../lldb/source/DataFormatters/TypeFormat.cpp | 6 +- .../DataFormatters/ValueObjectPrinter.cpp | 17 +- .../lldb/source/DataFormatters/VectorType.cpp | 25 +- .../lldb/source/Expression/CMakeLists.txt | 2 +- .../source/Expression/DWARFExpression.cpp | 605 ++-- .../source/Expression/DWARFExpressionList.cpp | 248 ++ .../source/Expression/ExpressionVariable.cpp | 6 +- .../lldb/source/Expression/FunctionCaller.cpp | 56 +- .../source/Expression/IRExecutionUnit.cpp | 414 ++- .../lldb/source/Expression/IRInterpreter.cpp | 161 +- .../lldb/source/Expression/IRMemoryMap.cpp | 19 +- .../source/Expression/LLVMUserExpression.cpp | 10 +- .../lldb/source/Expression/Materializer.cpp | 314 ++- gnu/llvm/lldb/source/Expression/REPL.cpp | 15 +- .../lldb/source/Expression/UserExpression.cpp | 75 +- .../source/Expression/UtilityFunction.cpp | 12 +- gnu/llvm/lldb/source/Host/CMakeLists.txt | 15 +- gnu/llvm/lldb/source/Host/common/Editline.cpp | 66 +- gnu/llvm/lldb/source/Host/common/File.cpp | 184 +- .../lldb/source/Host/common/FileAction.cpp | 6 +- .../lldb/source/Host/common/FileSystem.cpp | 146 +- gnu/llvm/lldb/source/Host/common/Host.cpp | 235 +- .../lldb/source/Host/common/HostInfoBase.cpp | 56 +- .../Host/common/HostNativeThreadBase.cpp | 21 +- .../lldb/source/Host/common/HostProcess.cpp | 11 +- .../lldb/source/Host/common/LockFileBase.cpp | 7 +- .../lldb/source/Host/common/MainLoopBase.cpp | 33 + .../Host/common/MonitoringProcessLauncher.cpp | 6 +- .../Host/common/NativeProcessProtocol.cpp | 87 +- .../Host/common/NativeRegisterContext.cpp | 31 +- .../source/Host/common/ProcessLaunchInfo.cpp | 48 +- .../source/Host/common/ProcessRunLock.cpp | 1 + .../source/Host/common/PseudoTerminal.cpp | 40 +- gnu/llvm/lldb/source/Host/common/Socket.cpp | 170 +- .../lldb/source/Host/common/TCPSocket.cpp | 80 +- gnu/llvm/lldb/source/Host/common/Terminal.cpp | 537 +++- .../source/Host/common/ThreadLauncher.cpp | 18 +- .../lldb/source/Host/common/UDPSocket.cpp | 32 +- gnu/llvm/lldb/source/Host/common/XML.cpp | 79 +- .../source/Host/freebsd/HostInfoFreeBSD.cpp | 30 +- gnu/llvm/lldb/source/Host/linux/Host.cpp | 15 +- .../lldb/source/Host/linux/HostInfoLinux.cpp | 43 +- gnu/llvm/lldb/source/Host/linux/Support.cpp | 7 +- .../lldb/source/Host/macosx/cfcpp/CFCBundle.h | 2 +- .../lldb/source/Host/macosx/cfcpp/CFCData.cpp | 2 +- .../lldb/source/Host/macosx/cfcpp/CFCData.h | 2 +- .../Host/macosx/cfcpp/CFCMutableArray.cpp | 9 +- .../Host/macosx/cfcpp/CFCMutableArray.h | 2 +- .../macosx/cfcpp/CFCMutableDictionary.cpp | 4 +- .../Host/macosx/cfcpp/CFCMutableDictionary.h | 2 +- .../Host/macosx/cfcpp/CFCMutableSet.cpp | 3 +- .../source/Host/macosx/cfcpp/CFCMutableSet.h | 2 +- .../source/Host/macosx/cfcpp/CFCString.cpp | 2 +- .../lldb/source/Host/macosx/cfcpp/CFCString.h | 2 +- .../source/Host/macosx/objcxx/CMakeLists.txt | 1 + .../lldb/source/Host/macosx/objcxx/Host.mm | 146 +- .../Host/macosx/objcxx/HostInfoMacOSX.mm | 223 +- .../Host/macosx/objcxx/HostThreadMacOSX.mm | 52 +- .../source/Host/netbsd/HostInfoNetBSD.cpp | 27 +- .../lldb/source/Host/netbsd/HostNetBSD.cpp | 11 +- .../posix/ConnectionFileDescriptorPosix.cpp | 569 ++-- .../source/Host/posix/FileSystemPosix.cpp | 7 +- .../lldb/source/Host/posix/HostInfoPosix.cpp | 32 +- .../source/Host/posix/HostProcessPosix.cpp | 34 +- .../lldb/source/Host/posix/LockFilePosix.cpp | 8 +- .../lldb/source/Host/posix/MainLoopPosix.cpp | 411 +++ .../Host/posix/ProcessLauncherPosixFork.cpp | 207 +- .../windows/ConnectionGenericFileWindows.cpp | 14 +- .../lldb/source/Host/windows/FileSystem.cpp | 8 +- gnu/llvm/lldb/source/Host/windows/Host.cpp | 19 +- .../source/Host/windows/HostInfoWindows.cpp | 22 +- .../Host/windows/HostProcessWindows.cpp | 58 +- .../source/Host/windows/HostThreadWindows.cpp | 4 +- .../source/Host/windows/LockFileWindows.cpp | 8 +- .../source/Host/windows/MainLoopWindows.cpp | 138 + .../lldb/source/Host/windows/PipeWindows.cpp | 6 +- .../Host/windows/ProcessLauncherWindows.cpp | 10 +- .../lldb/source/Interpreter/CMakeLists.txt | 4 +- .../lldb/source/Interpreter/CommandAlias.cpp | 14 +- .../source/Interpreter/CommandHistory.cpp | 17 +- .../source/Interpreter/CommandInterpreter.cpp | 544 +++- .../lldb/source/Interpreter/CommandObject.cpp | 449 +-- .../Interpreter/CommandReturnObject.cpp | 16 +- .../Interpreter/InterpreterProperties.td | 8 + .../source/Interpreter/OptionArgParser.cpp | 5 + .../Interpreter/OptionGroupArchitecture.cpp | 2 +- .../source/Interpreter/OptionGroupFormat.cpp | 40 +- .../Interpreter/OptionGroupMemoryTag.cpp | 60 + .../Interpreter/OptionGroupOutputFile.cpp | 2 +- .../Interpreter/OptionGroupPlatform.cpp | 26 +- .../source/Interpreter/OptionGroupUUID.cpp | 2 +- .../OptionGroupValueObjectDisplay.cpp | 14 +- .../Interpreter/OptionGroupVariable.cpp | 8 +- .../Interpreter/OptionGroupWatchpoint.cpp | 2 +- .../source/Interpreter/OptionValueArray.cpp | 36 +- .../source/Interpreter/OptionValueBoolean.cpp | 2 +- .../Interpreter/OptionValueDictionary.cpp | 34 +- .../Interpreter/OptionValueFileColonLine.cpp | 5 +- .../Interpreter/OptionValueFileSpec.cpp | 4 +- .../Interpreter/OptionValueFileSpecList.cpp | 28 +- .../source/Interpreter/OptionValueFormat.cpp | 4 + .../Interpreter/OptionValueFormatEntity.cpp | 7 + .../Interpreter/OptionValueLanguage.cpp | 4 + .../Interpreter/OptionValuePathMappings.cpp | 54 +- .../Interpreter/OptionValueProperties.cpp | 66 +- .../source/Interpreter/OptionValueSInt64.cpp | 8 +- .../source/Interpreter/OptionValueUInt64.cpp | 10 +- gnu/llvm/lldb/source/Interpreter/Options.cpp | 246 +- gnu/llvm/lldb/source/Interpreter/Property.cpp | 44 +- .../source/Interpreter/ScriptInterpreter.cpp | 35 +- .../Interpreter/embedded_interpreter.py | 73 +- .../source/Plugins/ABI/AArch64/ABIAArch64.cpp | 82 +- .../source/Plugins/ABI/AArch64/ABIAArch64.h | 9 +- .../Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp | 60 +- .../Plugins/ABI/AArch64/ABIMacOSX_arm64.h | 8 +- .../Plugins/ABI/AArch64/ABISysV_arm64.h | 6 +- .../source/Plugins/ABI/AArch64/CMakeLists.txt | 1 + .../source/Plugins/ABI/ARC/ABISysV_arc.cpp | 52 +- .../lldb/source/Plugins/ABI/ARC/ABISysV_arc.h | 12 +- .../source/Plugins/ABI/ARC/CMakeLists.txt | 1 + .../source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp | 353 +-- .../source/Plugins/ABI/ARM/ABIMacOSX_arm.h | 6 +- .../source/Plugins/ABI/ARM/ABISysV_arm.cpp | 358 +-- .../lldb/source/Plugins/ABI/ARM/ABISysV_arm.h | 6 +- .../source/Plugins/ABI/ARM/CMakeLists.txt | 1 + .../Plugins/ABI/Hexagon/ABISysV_hexagon.cpp | 265 +- .../Plugins/ABI/Hexagon/ABISysV_hexagon.h | 6 +- .../source/Plugins/ABI/Hexagon/CMakeLists.txt | 1 + .../source/Plugins/ABI/Mips/ABISysV_mips.cpp | 162 +- .../source/Plugins/ABI/Mips/ABISysV_mips.h | 6 +- .../Plugins/ABI/Mips/ABISysV_mips64.cpp | 174 +- .../source/Plugins/ABI/Mips/ABISysV_mips64.h | 6 +- .../source/Plugins/ABI/Mips/CMakeLists.txt | 1 + .../Plugins/ABI/PowerPC/ABISysV_ppc.cpp | 71 +- .../source/Plugins/ABI/PowerPC/ABISysV_ppc.h | 6 +- .../Plugins/ABI/PowerPC/ABISysV_ppc64.cpp | 45 +- .../Plugins/ABI/PowerPC/ABISysV_ppc64.h | 6 +- .../source/Plugins/ABI/PowerPC/CMakeLists.txt | 1 + .../Plugins/ABI/SystemZ/ABISysV_s390x.cpp | 46 +- .../Plugins/ABI/SystemZ/ABISysV_s390x.h | 6 +- .../source/Plugins/ABI/SystemZ/CMakeLists.txt | 1 + .../source/Plugins/ABI/X86/ABIMacOSX_i386.cpp | 18 +- .../source/Plugins/ABI/X86/ABIMacOSX_i386.h | 12 +- .../source/Plugins/ABI/X86/ABISysV_i386.cpp | 29 +- .../source/Plugins/ABI/X86/ABISysV_i386.h | 12 +- .../source/Plugins/ABI/X86/ABISysV_x86_64.cpp | 55 +- .../source/Plugins/ABI/X86/ABISysV_x86_64.h | 7 +- .../Plugins/ABI/X86/ABIWindows_x86_64.cpp | 45 +- .../Plugins/ABI/X86/ABIWindows_x86_64.h | 17 +- .../lldb/source/Plugins/ABI/X86/ABIX86.cpp | 243 +- gnu/llvm/lldb/source/Plugins/ABI/X86/ABIX86.h | 8 +- .../lldb/source/Plugins/ABI/X86/ABIX86_64.h | 7 +- .../source/Plugins/ABI/X86/ABIX86_i386.cpp | 22 + .../lldb/source/Plugins/ABI/X86/ABIX86_i386.h | 22 + .../source/Plugins/ABI/X86/CMakeLists.txt | 2 + .../AArch64/ArchitectureAArch64.cpp | 9 - .../AArch64/ArchitectureAArch64.h | 5 +- .../Architecture/Arm/ArchitectureArm.cpp | 7 - .../Architecture/Arm/ArchitectureArm.h | 5 +- .../Architecture/Mips/ArchitectureMips.cpp | 10 +- .../Architecture/Mips/ArchitectureMips.h | 5 +- .../Architecture/PPC64/ArchitecturePPC64.cpp | 7 - .../Architecture/PPC64/ArchitecturePPC64.h | 5 +- gnu/llvm/lldb/source/Plugins/CMakeLists.txt | 3 +- .../Plugins/Disassembler/LLVMC/CMakeLists.txt | 1 + .../Disassembler/LLVMC/DisassemblerLLVMC.cpp | 480 +++- .../Disassembler/LLVMC/DisassemblerLLVMC.h | 13 +- .../Darwin-Kernel/CMakeLists.txt | 1 - .../DynamicLoaderDarwinKernel.cpp | 199 +- .../Darwin-Kernel/DynamicLoaderDarwinKernel.h | 8 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 26 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.h | 8 +- .../Hexagon-DYLD/HexagonDYLDRendezvous.cpp | 10 +- .../DynamicLoader/MacOSX-DYLD/CMakeLists.txt | 1 + .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 100 +- .../MacOSX-DYLD/DynamicLoaderDarwin.h | 2 + .../MacOSX-DYLD/DynamicLoaderMacOS.cpp | 144 +- .../MacOSX-DYLD/DynamicLoaderMacOS.h | 16 +- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 73 +- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h | 8 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.h | 13 + .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 14 +- .../Static/DynamicLoaderStatic.cpp | 14 +- .../Static/DynamicLoaderStatic.h | 8 +- .../DynamicLoader/Windows-DYLD/CMakeLists.txt | 1 + .../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 58 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.h | 7 +- .../wasm-DYLD/DynamicLoaderWasmDYLD.cpp | 26 +- .../wasm-DYLD/DynamicLoaderWasmDYLD.h | 12 +- .../Clang/ASTResultSynthesizer.cpp | 50 +- .../Plugins/ExpressionParser/Clang/ASTUtils.h | 3 +- .../ExpressionParser/Clang/CMakeLists.txt | 2 + .../Clang/ClangASTImporter.cpp | 97 +- .../ExpressionParser/Clang/ClangASTImporter.h | 10 +- .../ExpressionParser/Clang/ClangASTSource.cpp | 106 +- .../ExpressionParser/Clang/ClangASTSource.h | 2 +- .../ExpressionParser/Clang/ClangDeclVendor.h | 2 +- .../Clang/ClangExpressionDeclMap.cpp | 337 ++- .../Clang/ClangExpressionDeclMap.h | 38 +- .../Clang/ClangExpressionParser.cpp | 49 +- .../Clang/ClangExpressionParser.h | 2 +- .../Clang/ClangExpressionSourceCode.cpp | 62 +- .../Clang/ClangExpressionSourceCode.h | 16 +- .../Clang/ClangExpressionUtil.cpp | 27 + .../Clang/ClangExpressionUtil.h | 30 + .../Clang/ClangExpressionVariable.h | 8 +- .../Clang/ClangExternalASTSourceCallbacks.cpp | 3 +- .../Clang/ClangExternalASTSourceCallbacks.h | 3 +- .../Clang/ClangFunctionCaller.cpp | 3 +- .../Clang/ClangFunctionCaller.h | 1 - .../ExpressionParser/Clang/ClangHost.cpp | 21 +- .../Clang/ClangModulesDeclVendor.cpp | 113 +- .../Clang/ClangPersistentVariables.cpp | 16 +- .../Clang/ClangPersistentVariables.h | 7 +- .../Clang/ClangUserExpression.cpp | 80 +- .../Clang/ClangUserExpression.h | 9 +- .../ExpressionParser/Clang/ClangUtil.cpp | 2 +- .../Clang/ClangUtilityFunction.cpp | 14 +- .../Clang/CppModuleConfiguration.cpp | 64 +- .../Clang/CppModuleConfiguration.h | 21 +- .../Clang/CxxModuleHandler.cpp | 26 +- .../ExpressionParser/Clang/CxxModuleHandler.h | 5 +- .../Clang/IRDynamicChecks.cpp | 16 +- .../ExpressionParser/Clang/IRDynamicChecks.h | 2 +- .../ExpressionParser/Clang/IRForTarget.cpp | 129 +- .../Clang/NameSearchContext.cpp | 12 +- .../Instruction/ARM/EmulateInstructionARM.cpp | 785 +++--- .../Instruction/ARM/EmulateInstructionARM.h | 18 +- .../Instruction/ARM/EmulationStateARM.cpp | 124 +- .../Instruction/ARM/EmulationStateARM.h | 9 +- .../ARM64/EmulateInstructionARM64.cpp | 158 +- .../ARM64/EmulateInstructionARM64.h | 13 +- .../source/Plugins/Instruction/CMakeLists.txt | 2 + .../Instruction/LoongArch/CMakeLists.txt | 11 + .../LoongArch/EmulateInstructionLoongArch.cpp | 544 ++++ .../LoongArch/EmulateInstructionLoongArch.h | 108 + .../MIPS/EmulateInstructionMIPS.cpp | 327 ++- .../Instruction/MIPS/EmulateInstructionMIPS.h | 15 +- .../MIPS64/EmulateInstructionMIPS64.cpp | 241 +- .../MIPS64/EmulateInstructionMIPS64.h | 15 +- .../PPC64/EmulateInstructionPPC64.cpp | 81 +- .../PPC64/EmulateInstructionPPC64.h | 13 +- .../Plugins/Instruction/RISCV/CMakeLists.txt | 11 + .../RISCV/EmulateInstructionRISCV.cpp | 1780 ++++++++++++ .../RISCV/EmulateInstructionRISCV.h | 106 + .../Instruction/RISCV/RISCVCInstructions.h | 357 +++ .../Instruction/RISCV/RISCVInstructions.h | 352 +++ .../ASan/InstrumentationRuntimeASan.cpp | 21 +- .../ASan/InstrumentationRuntimeASan.h | 8 +- ...nstrumentationRuntimeMainThreadChecker.cpp | 14 +- .../InstrumentationRuntimeMainThreadChecker.h | 8 +- .../TSan/InstrumentationRuntimeTSan.cpp | 123 +- .../TSan/InstrumentationRuntimeTSan.h | 8 +- .../UBSan/InstrumentationRuntimeUBSan.cpp | 15 +- .../UBSan/InstrumentationRuntimeUBSan.h | 10 +- .../Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 44 +- .../Plugins/JITLoader/GDB/JITLoaderGDB.h | 8 +- .../Language/CPlusPlus/BlockPointer.cpp | 12 +- .../Plugins/Language/CPlusPlus/CMakeLists.txt | 7 +- .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 676 ++++- .../Language/CPlusPlus/CPlusPlusLanguage.h | 63 +- .../CPlusPlus/CPlusPlusNameParser.cpp | 157 +- .../Language/CPlusPlus/CPlusPlusNameParser.h | 24 +- .../Plugins/Language/CPlusPlus/Coroutines.cpp | 225 ++ .../Plugins/Language/CPlusPlus/Coroutines.h | 60 + .../Language/CPlusPlus/CxxStringTypes.cpp | 214 +- .../Plugins/Language/CPlusPlus/Generic.h | 25 + .../Language/CPlusPlus/GenericBitset.cpp | 150 + .../Language/CPlusPlus/GenericOptional.cpp | 139 + .../Plugins/Language/CPlusPlus/LibCxx.cpp | 473 +++- .../Plugins/Language/CPlusPlus/LibCxx.h | 87 +- .../Language/CPlusPlus/LibCxxAtomic.cpp | 4 +- .../CPlusPlus/LibCxxInitializerList.cpp | 20 +- .../Plugins/Language/CPlusPlus/LibCxxList.cpp | 16 +- .../Plugins/Language/CPlusPlus/LibCxxMap.cpp | 61 +- .../CPlusPlus/LibCxxRangesRefView.cpp | 87 + .../Plugins/Language/CPlusPlus/LibCxxSpan.cpp | 152 + .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 70 +- .../Language/CPlusPlus/LibCxxVariant.cpp | 64 +- .../Language/CPlusPlus/LibCxxVariant.h | 3 +- .../Language/CPlusPlus/LibCxxVector.cpp | 22 +- .../Plugins/Language/CPlusPlus/LibStdcpp.cpp | 30 +- .../Plugins/Language/CPlusPlus/LibStdcpp.h | 8 + .../CPlusPlus/MSVCUndecoratedNameParser.cpp | 9 +- .../Language/ClangCommon/ClangHighlighter.cpp | 3 +- .../Language/ClangCommon/ClangHighlighter.h | 3 +- .../lldb/source/Plugins/Language/ObjC/CF.cpp | 10 +- .../Plugins/Language/ObjC/CFBasicHash.h | 2 +- .../source/Plugins/Language/ObjC/Cocoa.cpp | 87 +- .../Plugins/Language/ObjC/CoreMedia.cpp | 7 +- .../source/Plugins/Language/ObjC/NSArray.cpp | 75 +- .../Plugins/Language/ObjC/NSDictionary.cpp | 261 +- .../source/Plugins/Language/ObjC/NSError.cpp | 21 +- .../Plugins/Language/ObjC/NSException.cpp | 22 +- .../Plugins/Language/ObjC/NSIndexPath.cpp | 20 +- .../source/Plugins/Language/ObjC/NSSet.cpp | 36 +- .../source/Plugins/Language/ObjC/NSString.cpp | 51 +- .../Plugins/Language/ObjC/ObjCConstants.h | 44 + .../Plugins/Language/ObjC/ObjCLanguage.cpp | 66 +- .../Plugins/Language/ObjC/ObjCLanguage.h | 8 +- .../ObjCPlusPlus/ObjCPlusPlusLanguage.cpp | 12 - .../ObjCPlusPlus/ObjCPlusPlusLanguage.h | 6 +- .../CPlusPlus/CPPLanguageRuntime.cpp | 40 +- .../CPlusPlus/CPPLanguageRuntime.h | 2 +- .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 24 +- .../ItaniumABI/ItaniumABILanguageRuntime.h | 6 +- .../AppleObjCClassDescriptorV2.cpp | 17 +- .../AppleObjCClassDescriptorV2.h | 12 +- .../AppleObjCRuntime/AppleObjCDeclVendor.cpp | 64 +- .../AppleObjCRuntime/AppleObjCDeclVendor.h | 2 +- .../AppleObjCRuntime/AppleObjCRuntime.cpp | 31 +- .../ObjC/AppleObjCRuntime/AppleObjCRuntime.h | 4 +- .../AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 19 +- .../AppleObjCRuntime/AppleObjCRuntimeV1.h | 6 +- .../AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 575 ++-- .../AppleObjCRuntime/AppleObjCRuntimeV2.h | 74 +- .../AppleObjCTrampolineHandler.cpp | 568 ++-- .../AppleObjCTrampolineHandler.h | 22 +- .../AppleObjCTypeEncodingParser.cpp | 85 +- .../AppleObjCTypeEncodingParser.h | 6 +- ...pleThreadPlanStepThroughObjCTrampoline.cpp | 47 +- ...AppleThreadPlanStepThroughObjCTrampoline.h | 10 +- .../ObjC/ObjCLanguageRuntime.cpp | 51 +- .../ObjC/ObjCLanguageRuntime.h | 59 +- .../RenderScriptExpressionOpts.cpp | 18 +- .../RenderScriptExpressionOpts.h | 3 +- .../RenderScriptRuntime.cpp | 198 +- .../RenderScriptRuntime/RenderScriptRuntime.h | 9 +- .../RenderScriptScriptGroup.cpp | 5 +- .../RenderScriptx86ABIFixups.cpp | 67 +- .../MemoryHistory/asan/MemoryHistoryASan.cpp | 15 +- .../MemoryHistory/asan/MemoryHistoryASan.h | 8 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 242 +- .../BSD-Archive/ObjectContainerBSDArchive.h | 34 +- .../Plugins/ObjectContainer/CMakeLists.txt | 1 + .../Mach-O-Fileset/CMakeLists.txt | 10 + .../ObjectContainerMachOFileset.cpp | 299 ++ .../ObjectContainerMachOFileset.h | 94 + .../ObjectContainerUniversalMachO.cpp | 39 - .../ObjectContainerUniversalMachO.h | 12 +- .../ObjectFile/Breakpad/BreakpadRecords.cpp | 179 +- .../ObjectFile/Breakpad/BreakpadRecords.h | 73 +- .../ObjectFile/Breakpad/CMakeLists.txt | 1 + .../Breakpad/ObjectFileBreakpad.cpp | 37 +- .../ObjectFile/Breakpad/ObjectFileBreakpad.h | 12 +- .../source/Plugins/ObjectFile/CMakeLists.txt | 3 +- .../Plugins/ObjectFile/ELF/ELFHeader.cpp | 6 + .../Plugins/ObjectFile/ELF/ObjectFileELF.h | 36 +- .../Plugins/ObjectFile/JIT/ObjectFileJIT.cpp | 40 +- .../Plugins/ObjectFile/JIT/ObjectFileJIT.h | 16 +- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 1062 +++---- .../ObjectFile/Mach-O/ObjectFileMachO.h | 41 +- .../ObjectFile/Minidump/CMakeLists.txt | 14 + .../Minidump/MinidumpFileBuilder.cpp | 774 ++++++ .../ObjectFile/Minidump/MinidumpFileBuilder.h | 92 + .../Minidump/ObjectFileMinidump.cpp | 114 + .../ObjectFile/Minidump/ObjectFileMinidump.h | 66 + .../Plugins/ObjectFile/PDB/ObjectFilePDB.cpp | 13 +- .../Plugins/ObjectFile/PDB/ObjectFilePDB.h | 14 +- .../Plugins/ObjectFile/PECOFF/CMakeLists.txt | 13 + .../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 546 ++-- .../ObjectFile/PECOFF/ObjectFilePECOFF.h | 138 +- .../PECOFF/ObjectFilePECOFFProperties.td | 14 + .../ObjectFile/PECOFF/PECallFrameInfo.cpp | 18 +- .../ObjectFile/PECOFF/WindowsMiniDump.cpp | 2 +- .../ObjectFile/wasm/ObjectFileWasm.cpp | 41 +- .../Plugins/ObjectFile/wasm/ObjectFileWasm.h | 18 +- .../Python/OperatingSystemPython.cpp | 24 +- .../Python/OperatingSystemPython.h | 17 +- .../Plugins/Platform/Android/AdbClient.cpp | 43 +- .../Platform/Android/PlatformAndroid.cpp | 64 +- .../Platform/Android/PlatformAndroid.h | 12 +- .../PlatformAndroidRemoteGDBServer.cpp | 93 +- .../Android/PlatformAndroidRemoteGDBServer.h | 9 +- .../source/Plugins/Platform/CMakeLists.txt | 25 +- .../Plugins/Platform/FreeBSD/CMakeLists.txt | 3 + .../Platform/FreeBSD/PlatformFreeBSD.cpp | 199 +- .../Platform/FreeBSD/PlatformFreeBSD.h | 26 +- .../Plugins/Platform/Linux/PlatformLinux.cpp | 370 ++- .../Plugins/Platform/Linux/PlatformLinux.h | 29 +- .../Plugins/Platform/MacOSX/CMakeLists.txt | 4 + .../MacOSX/PlatformAppleSimulator.cpp | 121 +- .../Platform/MacOSX/PlatformAppleSimulator.h | 110 +- .../Platform/MacOSX/PlatformDarwin.cpp | 1158 +++----- .../Plugins/Platform/MacOSX/PlatformDarwin.h | 169 +- .../Platform/MacOSX/PlatformDarwinDevice.cpp | 466 ++++ .../Platform/MacOSX/PlatformDarwinDevice.h | 67 + .../Platform/MacOSX/PlatformDarwinKernel.cpp | 178 +- .../Platform/MacOSX/PlatformDarwinKernel.h | 241 +- .../Platform/MacOSX/PlatformMacOSX.cpp | 86 +- .../Plugins/Platform/MacOSX/PlatformMacOSX.h | 77 +- .../MacOSX/PlatformMacOSXProperties.td | 9 + .../MacOSX/PlatformRemoteAppleBridge.cpp | 41 +- .../MacOSX/PlatformRemoteAppleBridge.h | 38 +- .../Platform/MacOSX/PlatformRemoteAppleTV.cpp | 91 +- .../Platform/MacOSX/PlatformRemoteAppleTV.h | 30 +- .../MacOSX/PlatformRemoteAppleWatch.cpp | 166 +- .../MacOSX/PlatformRemoteAppleWatch.h | 39 +- .../MacOSX/PlatformRemoteDarwinDevice.cpp | 315 +-- .../MacOSX/PlatformRemoteDarwinDevice.h | 102 +- .../Platform/MacOSX/PlatformRemoteMacOSX.cpp | 95 +- .../Platform/MacOSX/PlatformRemoteMacOSX.h | 44 +- .../Platform/MacOSX/PlatformRemoteiOS.cpp | 25 +- .../Platform/MacOSX/PlatformRemoteiOS.h | 37 +- ...PlatformiOSSimulatorCoreSimulatorSupport.h | 10 +- ...latformiOSSimulatorCoreSimulatorSupport.mm | 36 +- .../Platform/NetBSD/PlatformNetBSD.cpp | 225 +- .../Plugins/Platform/NetBSD/PlatformNetBSD.h | 26 +- .../Plugins/Platform/POSIX/CMakeLists.txt | 1 + .../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 187 +- .../Plugins/Platform/POSIX/PlatformPOSIX.h | 6 +- .../Plugins/Platform/QemuUser/CMakeLists.txt | 20 + .../Platform/QemuUser/PlatformQemuUser.cpp | 247 ++ .../Platform/QemuUser/PlatformQemuUser.h | 81 + .../QemuUser/PlatformQemuUserProperties.td | 24 + .../Plugins/Platform/Windows/CMakeLists.txt | 4 + .../Platform/Windows/PlatformWindows.cpp | 624 ++++- .../Platform/Windows/PlatformWindows.h | 45 +- .../Platform/gdb-server/CMakeLists.txt | 1 + .../gdb-server/PlatformRemoteGDBServer.cpp | 436 ++- .../gdb-server/PlatformRemoteGDBServer.h | 40 +- .../Process/FreeBSD/NativeProcessFreeBSD.cpp | 92 +- .../Process/FreeBSD/NativeProcessFreeBSD.h | 2 + .../NativeRegisterContextFreeBSD_arm.cpp | 4 +- .../NativeRegisterContextFreeBSD_arm.h | 2 +- .../NativeRegisterContextFreeBSD_arm64.cpp | 6 +- .../NativeRegisterContextFreeBSD_arm64.h | 2 +- .../NativeRegisterContextFreeBSD_mips64.cpp | 63 +- .../NativeRegisterContextFreeBSD_mips64.h | 8 +- .../NativeRegisterContextFreeBSD_powerpc.cpp | 15 +- .../NativeRegisterContextFreeBSD_powerpc.h | 5 +- .../NativeRegisterContextFreeBSD_x86_64.cpp | 31 +- .../NativeRegisterContextFreeBSD_x86_64.h | 7 +- .../Process/FreeBSD/NativeThreadFreeBSD.cpp | 45 +- .../Process/FreeBSD/NativeThreadFreeBSD.h | 3 + .../Process/FreeBSDKernel/CMakeLists.txt | 27 + .../FreeBSDKernel/ProcessFreeBSDKernel.cpp | 327 +++ .../FreeBSDKernel/ProcessFreeBSDKernel.h | 53 + .../RegisterContextFreeBSDKernel_arm64.cpp | 110 + .../RegisterContextFreeBSDKernel_arm64.h | 41 + .../RegisterContextFreeBSDKernel_i386.cpp | 83 + .../RegisterContextFreeBSDKernel_i386.h | 41 + .../RegisterContextFreeBSDKernel_x86_64.cpp | 88 + .../RegisterContextFreeBSDKernel_x86_64.h | 41 + .../FreeBSDKernel/ThreadFreeBSDKernel.cpp | 86 + .../FreeBSDKernel/ThreadFreeBSDKernel.h | 50 + .../Plugins/Process/Linux/CMakeLists.txt | 11 +- .../Process/Linux/IntelPTCollector.cpp | 265 ++ .../Plugins/Process/Linux/IntelPTCollector.h | 91 + .../Process/Linux/IntelPTMultiCoreTrace.cpp | 165 ++ .../Process/Linux/IntelPTMultiCoreTrace.h | 113 + .../Linux/IntelPTPerThreadProcessTrace.cpp | 67 + .../Linux/IntelPTPerThreadProcessTrace.h | 63 + .../Process/Linux/IntelPTProcessTrace.h | 53 + .../Linux/IntelPTSingleBufferTrace.cpp | 289 ++ .../Process/Linux/IntelPTSingleBufferTrace.h | 115 + .../Linux/IntelPTThreadTraceCollection.cpp | 92 + .../Linux/IntelPTThreadTraceCollection.h | 77 + .../Process/Linux/NativeProcessLinux.cpp | 489 ++-- .../Process/Linux/NativeProcessLinux.h | 38 +- .../Linux/NativeRegisterContextLinux.cpp | 38 +- .../Linux/NativeRegisterContextLinux.h | 24 +- .../Linux/NativeRegisterContextLinux_arm.cpp | 70 +- .../Linux/NativeRegisterContextLinux_arm.h | 2 +- .../NativeRegisterContextLinux_arm64.cpp | 23 +- .../Linux/NativeRegisterContextLinux_arm64.h | 2 +- ...NativeRegisterContextLinux_loongarch64.cpp | 338 +++ .../NativeRegisterContextLinux_loongarch64.h | 93 + .../NativeRegisterContextLinux_ppc64le.cpp | 40 +- .../NativeRegisterContextLinux_ppc64le.h | 4 +- .../NativeRegisterContextLinux_riscv64.cpp | 349 +++ .../NativeRegisterContextLinux_riscv64.h | 92 + .../NativeRegisterContextLinux_s390x.cpp | 13 +- .../Linux/NativeRegisterContextLinux_s390x.h | 2 +- .../NativeRegisterContextLinux_x86_64.cpp | 18 +- .../Linux/NativeRegisterContextLinux_x86_64.h | 7 +- .../Process/Linux/NativeThreadLinux.cpp | 54 +- .../Plugins/Process/Linux/NativeThreadLinux.h | 5 + .../source/Plugins/Process/Linux/Perf.cpp | 380 +++ .../lldb/source/Plugins/Process/Linux/Perf.h | 327 +++ .../source/Plugins/Process/Linux/Procfs.cpp | 70 + .../source/Plugins/Process/Linux/Procfs.h | 42 +- .../Plugins/Process/Linux/SingleStepCheck.cpp | 8 +- .../MacOSX-Kernel/CommunicationKDP.cpp | 14 +- .../Process/MacOSX-Kernel/CommunicationKDP.h | 6 +- .../Process/MacOSX-Kernel/ProcessKDP.cpp | 256 +- .../Process/MacOSX-Kernel/ProcessKDP.h | 20 +- .../Process/MacOSX-Kernel/ProcessKDPLog.cpp | 28 +- .../Process/MacOSX-Kernel/ProcessKDPLog.h | 41 +- .../MacOSX-Kernel/RegisterContextKDP_arm.h | 2 +- .../MacOSX-Kernel/RegisterContextKDP_arm64.h | 2 +- .../MacOSX-Kernel/RegisterContextKDP_i386.h | 2 +- .../MacOSX-Kernel/RegisterContextKDP_x86_64.h | 2 +- .../Process/MacOSX-Kernel/ThreadKDP.cpp | 4 +- .../Plugins/Process/MacOSX-Kernel/ThreadKDP.h | 2 +- .../Process/NetBSD/NativeProcessNetBSD.cpp | 57 +- .../Process/NetBSD/NativeProcessNetBSD.h | 2 + .../NativeRegisterContextNetBSD_x86_64.cpp | 27 +- .../NativeRegisterContextNetBSD_x86_64.h | 7 +- .../Process/NetBSD/NativeThreadNetBSD.cpp | 21 +- .../Process/POSIX/NativeProcessELF.cpp | 22 +- .../Plugins/Process/POSIX/NativeProcessELF.h | 7 +- .../Plugins/Process/POSIX/ProcessPOSIXLog.cpp | 20 +- .../Plugins/Process/POSIX/ProcessPOSIXLog.h | 36 +- .../source/Plugins/Process/Utility/ARMUtils.h | 7 +- .../Plugins/Process/Utility/AuxVector.cpp | 5 +- .../Plugins/Process/Utility/AuxVector.h | 3 +- .../Process/Utility/GDBRemoteSignals.cpp | 165 +- .../Process/Utility/GDBRemoteSignals.h | 3 +- .../Plugins/Process/Utility/HistoryThread.cpp | 5 +- .../Process/Utility/InferiorCallPOSIX.cpp | 27 +- .../Plugins/Process/Utility/LinuxProcMaps.cpp | 13 +- .../Utility/MemoryTagManagerAArch64MTE.cpp | 176 +- .../Utility/MemoryTagManagerAArch64MTE.h | 12 +- .../NativeProcessSoftwareSingleStep.cpp | 9 +- .../NativeRegisterContextDBReg_arm64.cpp | 27 +- .../NativeRegisterContextDBReg_x86.cpp | 16 +- .../Utility/RegisterContextDarwin_arm.cpp | 177 +- .../Utility/RegisterContextDarwin_arm.h | 2 +- .../Utility/RegisterContextDarwin_arm64.cpp | 17 +- .../Utility/RegisterContextDarwin_arm64.h | 2 +- .../Utility/RegisterContextDarwin_i386.cpp | 101 +- .../Utility/RegisterContextDarwin_i386.h | 2 +- .../Utility/RegisterContextDarwin_x86_64.cpp | 116 +- .../Utility/RegisterContextDarwin_x86_64.h | 2 +- .../Process/Utility/RegisterContextDummy.cpp | 3 +- .../Process/Utility/RegisterContextDummy.h | 2 +- .../Utility/RegisterContextFreeBSD_i386.cpp | 2 +- .../Utility/RegisterContextFreeBSD_mips64.cpp | 104 +- .../RegisterContextFreeBSD_powerpc.cpp | 5 +- .../Utility/RegisterContextHistory.cpp | 2 +- .../Process/Utility/RegisterContextHistory.h | 2 +- .../Utility/RegisterContextLinux_i386.cpp | 29 +- .../Utility/RegisterContextLinux_i386.h | 3 +- .../Utility/RegisterContextLinux_x86_64.cpp | 27 +- .../Utility/RegisterContextLinux_x86_64.h | 3 +- .../Process/Utility/RegisterContextMach_arm.h | 2 +- .../Utility/RegisterContextMach_i386.h | 2 +- .../Utility/RegisterContextMach_x86_64.h | 2 +- .../Process/Utility/RegisterContextMemory.cpp | 14 +- .../Process/Utility/RegisterContextMemory.h | 10 +- .../Utility/RegisterContextNetBSD_i386.cpp | 2 +- .../Utility/RegisterContextOpenBSD_i386.cpp | 2 +- .../RegisterContextPOSIX_loongarch64.cpp | 82 + .../RegisterContextPOSIX_loongarch64.h | 63 + .../Utility/RegisterContextPOSIX_riscv64.cpp | 82 + .../Utility/RegisterContextPOSIX_riscv64.h | 63 + .../Utility/RegisterContextPOSIX_s390x.cpp | 4 +- .../Utility/RegisterContextPOSIX_x86.cpp | 5 +- .../Utility/RegisterContextThreadMemory.cpp | 2 +- .../Utility/RegisterContextThreadMemory.h | 2 +- .../Utility/RegisterContextWindows_i386.cpp | 5 +- .../Utility/RegisterContextWindows_x86_64.cpp | 27 +- .../Process/Utility/RegisterInfoInterface.h | 4 +- .../Process/Utility/RegisterInfoPOSIX_arm.cpp | 2 +- .../Utility/RegisterInfoPOSIX_arm64.cpp | 28 +- .../Process/Utility/RegisterInfoPOSIX_arm64.h | 5 +- .../Utility/RegisterInfoPOSIX_loongarch64.cpp | 158 ++ .../Utility/RegisterInfoPOSIX_loongarch64.h | 69 + .../Utility/RegisterInfoPOSIX_riscv64.cpp | 142 + .../Utility/RegisterInfoPOSIX_riscv64.h | 61 + .../Process/Utility/RegisterInfos_arm.h | 1678 +++-------- .../Process/Utility/RegisterInfos_arm64.h | 19 +- .../Process/Utility/RegisterInfos_arm64_sve.h | 9 +- .../Process/Utility/RegisterInfos_i386.h | 24 +- .../Utility/RegisterInfos_loongarch64.h | 171 ++ .../Process/Utility/RegisterInfos_mips64.h | 96 +- .../Process/Utility/RegisterInfos_powerpc.h | 43 +- .../Process/Utility/RegisterInfos_ppc64.h | 45 +- .../Process/Utility/RegisterInfos_ppc64le.h | 51 +- .../Process/Utility/RegisterInfos_riscv64.h | 140 + .../Process/Utility/RegisterInfos_s390x.h | 26 +- .../Process/Utility/RegisterInfos_x86_64.h | 48 +- .../Process/Utility/StopInfoMachException.cpp | 275 +- .../Process/Utility/StopInfoMachException.h | 18 + .../Plugins/Process/Utility/ThreadMemory.cpp | 3 +- .../Utility/lldb-loongarch-register-enums.h | 178 ++ .../lldb-mips-freebsd-register-enums.h | 42 +- .../Utility/lldb-riscv-register-enums.h | 158 ++ .../Process/Windows/Common/DebuggerThread.cpp | 170 +- .../Process/Windows/Common/DebuggerThread.h | 2 - .../Process/Windows/Common/ExceptionRecord.h | 26 +- .../Windows/Common/NativeProcessWindows.cpp | 54 +- .../Windows/Common/NativeProcessWindows.h | 5 + .../NativeRegisterContextWindows_WoW64.cpp | 10 +- .../NativeRegisterContextWindows_WoW64.h | 2 +- .../NativeRegisterContextWindows_arm.cpp | 18 +- .../Common/NativeRegisterContextWindows_arm.h | 2 +- .../NativeRegisterContextWindows_arm64.cpp | 18 +- .../NativeRegisterContextWindows_arm64.h | 2 +- .../NativeRegisterContextWindows_i386.cpp | 10 +- .../NativeRegisterContextWindows_i386.h | 2 +- .../NativeRegisterContextWindows_x86_64.cpp | 14 +- .../NativeRegisterContextWindows_x86_64.h | 2 +- .../Windows/Common/NativeThreadWindows.cpp | 22 +- .../Windows/Common/ProcessDebugger.cpp | 35 +- .../Process/Windows/Common/ProcessWindows.cpp | 109 +- .../Process/Windows/Common/ProcessWindows.h | 21 +- .../Windows/Common/ProcessWindowsLog.cpp | 22 +- .../Windows/Common/ProcessWindowsLog.h | 30 +- .../Windows/Common/RegisterContextWindows.cpp | 6 +- .../Windows/Common/RegisterContextWindows.h | 2 +- .../Windows/Common/TargetThreadWindows.cpp | 23 +- .../Common/arm/RegisterContextWindows_arm.cpp | 14 +- .../arm64/RegisterContextWindows_arm64.cpp | 19 +- .../Common/x64/RegisterContextWindows_x64.cpp | 465 ++-- .../Common/x86/RegisterContextWindows_x86.cpp | 46 +- .../Process/elf-core/ProcessElfCore.cpp | 109 +- .../Plugins/Process/elf-core/ProcessElfCore.h | 35 +- .../elf-core/RegisterContextPOSIXCore_arm.cpp | 2 +- .../elf-core/RegisterContextPOSIXCore_arm.h | 2 +- .../RegisterContextPOSIXCore_arm64.cpp | 12 +- .../elf-core/RegisterContextPOSIXCore_arm64.h | 2 +- .../RegisterContextPOSIXCore_mips64.cpp | 2 +- .../RegisterContextPOSIXCore_mips64.h | 2 +- .../RegisterContextPOSIXCore_powerpc.cpp | 2 +- .../RegisterContextPOSIXCore_powerpc.h | 2 +- .../RegisterContextPOSIXCore_s390x.cpp | 2 +- .../elf-core/RegisterContextPOSIXCore_s390x.h | 2 +- .../RegisterContextPOSIXCore_x86_64.cpp | 4 +- .../RegisterContextPOSIXCore_x86_64.h | 2 +- .../Process/elf-core/RegisterUtilities.cpp | 7 +- .../Process/elf-core/ThreadElfCore.cpp | 3 +- .../Plugins/Process/gdb-remote/CMakeLists.txt | 9 +- .../gdb-remote/GDBRemoteClientBase.cpp | 64 +- .../Process/gdb-remote/GDBRemoteClientBase.h | 17 +- .../gdb-remote/GDBRemoteCommunication.cpp | 212 +- .../gdb-remote/GDBRemoteCommunication.h | 70 +- .../GDBRemoteCommunicationClient.cpp | 955 ++++--- .../gdb-remote/GDBRemoteCommunicationClient.h | 115 +- .../GDBRemoteCommunicationHistory.cpp | 4 - .../GDBRemoteCommunicationHistory.h | 10 - .../GDBRemoteCommunicationServer.cpp | 13 +- .../gdb-remote/GDBRemoteCommunicationServer.h | 7 +- .../GDBRemoteCommunicationServerCommon.h | 6 +- .../GDBRemoteCommunicationServerLLGS.cpp | 1155 +++++--- .../GDBRemoteCommunicationServerLLGS.h | 77 +- .../GDBRemoteCommunicationServerPlatform.cpp | 45 +- .../GDBRemoteCommunicationServerPlatform.h | 6 +- .../Process/gdb-remote/GDBRemoteErrno.def | 39 + .../gdb-remote/GDBRemoteRegisterContext.cpp | 417 +-- .../gdb-remote/GDBRemoteRegisterContext.h | 7 +- .../gdb-remote/GDBRemoteRegisterFallback.cpp | 86 + .../gdb-remote/GDBRemoteRegisterFallback.h | 26 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 2466 ++++++++--------- .../Process/gdb-remote/ProcessGDBRemote.h | 85 +- .../gdb-remote/ProcessGDBRemoteLog.cpp | 28 +- .../Process/gdb-remote/ProcessGDBRemoteLog.h | 40 +- .../Process/gdb-remote/ThreadGDBRemote.cpp | 28 +- .../Process/gdb-remote/ThreadGDBRemote.h | 3 + .../Process/mach-core/ProcessMachCore.cpp | 422 ++- .../Process/mach-core/ProcessMachCore.h | 27 +- .../Process/mach-core/ThreadMachCore.cpp | 50 +- .../Process/minidump/MinidumpParser.cpp | 66 +- .../Plugins/Process/minidump/MinidumpParser.h | 8 +- .../Process/minidump/MinidumpTypes.cpp | 13 +- .../Plugins/Process/minidump/MinidumpTypes.h | 6 +- .../Process/minidump/ProcessMinidump.cpp | 51 +- .../Process/minidump/ProcessMinidump.h | 25 +- .../minidump/RegisterContextMinidump_ARM.cpp | 50 +- .../RegisterContextMinidump_ARM64.cpp | 47 +- .../RegisterContextMinidump_x86_32.cpp | 2 +- .../RegisterContextMinidump_x86_64.cpp | 2 +- .../Plugins/Process/scripted/CMakeLists.txt | 1 + .../Process/scripted/ScriptedProcess.cpp | 309 ++- .../Process/scripted/ScriptedProcess.h | 58 +- .../Process/scripted/ScriptedThread.cpp | 359 +++ .../Plugins/Process/scripted/ScriptedThread.h | 80 + .../lldb/source/Plugins/REPL/CMakeLists.txt | 1 + .../source/Plugins/REPL/Clang/CMakeLists.txt | 17 + .../source/Plugins/REPL/Clang/ClangREPL.cpp | 102 + .../source/Plugins/REPL/Clang/ClangREPL.h | 63 + .../ScriptInterpreter/Lua/CMakeLists.txt | 2 - .../Plugins/ScriptInterpreter/Lua/Lua.cpp | 33 +- .../ScriptInterpreter/Lua/SWIGLuaBridge.h | 28 + .../Lua/ScriptInterpreterLua.cpp | 24 +- .../Lua/ScriptInterpreterLua.h | 10 +- .../None/ScriptInterpreterNone.cpp | 13 +- .../None/ScriptInterpreterNone.h | 8 +- .../ScriptInterpreter/Python/CMakeLists.txt | 18 +- .../Python/PythonDataObjects.cpp | 216 +- .../Python/PythonDataObjects.h | 107 +- .../Python/PythonReadline.cpp | 27 +- .../Python/SWIGPythonBridge.h | 233 +- .../Python/ScriptInterpreterPython.cpp | 843 ++---- .../Python/ScriptInterpreterPython.h | 18 +- .../Python/ScriptInterpreterPythonImpl.h | 30 +- .../ScriptedPlatformPythonInterface.cpp | 108 + .../Python/ScriptedPlatformPythonInterface.h | 44 + .../Python/ScriptedProcessPythonInterface.cpp | 312 +-- .../Python/ScriptedProcessPythonInterface.h | 35 +- .../Python/ScriptedPythonInterface.cpp | 92 + .../Python/ScriptedPythonInterface.h | 214 ++ .../Python/ScriptedThreadPythonInterface.cpp | 159 ++ .../Python/ScriptedThreadPythonInterface.h | 52 + .../ScriptInterpreter/Python/lldb-python.h | 7 + .../DarwinLog/StructuredDataDarwinLog.cpp | 84 +- .../DarwinLog/StructuredDataDarwinLog.h | 6 +- .../Breakpad/SymbolFileBreakpad.cpp | 228 +- .../SymbolFile/Breakpad/SymbolFileBreakpad.h | 39 +- .../source/Plugins/SymbolFile/CMakeLists.txt | 2 +- .../SymbolFile/DWARF/AppleDWARFIndex.cpp | 20 +- .../SymbolFile/DWARF/AppleDWARFIndex.h | 6 +- .../Plugins/SymbolFile/DWARF/CMakeLists.txt | 1 + .../Plugins/SymbolFile/DWARF/DIERef.cpp | 38 + .../source/Plugins/SymbolFile/DWARF/DIERef.h | 43 +- .../SymbolFile/DWARF/DWARFASTParser.cpp | 116 + .../Plugins/SymbolFile/DWARF/DWARFASTParser.h | 15 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 2054 +++++++------- .../SymbolFile/DWARF/DWARFASTParserClang.h | 93 +- .../DWARF/DWARFAbbreviationDeclaration.cpp | 4 +- .../SymbolFile/DWARF/DWARFAttribute.cpp | 2 + .../Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp | 12 +- .../Plugins/SymbolFile/DWARF/DWARFBaseDIE.h | 6 +- .../SymbolFile/DWARF/DWARFCompileUnit.cpp | 39 +- .../Plugins/SymbolFile/DWARF/DWARFContext.cpp | 21 +- .../Plugins/SymbolFile/DWARF/DWARFContext.h | 6 +- .../Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 41 +- .../Plugins/SymbolFile/DWARF/DWARFDIE.h | 22 +- .../SymbolFile/DWARF/DWARFDataExtractor.cpp | 6 +- .../SymbolFile/DWARF/DWARFDebugAbbrev.cpp | 1 - .../SymbolFile/DWARF/DWARFDebugArangeSet.cpp | 2 +- .../SymbolFile/DWARF/DWARFDebugAranges.cpp | 2 +- .../SymbolFile/DWARF/DWARFDebugInfo.cpp | 32 +- .../Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 2 - .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 112 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.h | 12 +- .../SymbolFile/DWARF/DWARFDebugMacro.cpp | 1 + .../SymbolFile/DWARF/DWARFDebugMacro.h | 6 +- .../SymbolFile/DWARF/DWARFDeclContext.cpp | 2 + .../SymbolFile/DWARF/DWARFDeclContext.h | 5 - .../SymbolFile/DWARF/DWARFFormValue.cpp | 20 +- .../Plugins/SymbolFile/DWARF/DWARFFormValue.h | 8 +- .../Plugins/SymbolFile/DWARF/DWARFIndex.cpp | 31 +- .../Plugins/SymbolFile/DWARF/DWARFIndex.h | 15 +- .../SymbolFile/DWARF/DWARFTypeUnit.cpp | 11 +- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 409 +-- .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 104 +- .../SymbolFile/DWARF/DebugNamesDWARFIndex.cpp | 50 +- .../SymbolFile/DWARF/DebugNamesDWARFIndex.h | 9 +- .../SymbolFile/DWARF/HashedNameToDIE.cpp | 8 +- .../SymbolFile/DWARF/HashedNameToDIE.h | 2 +- .../SymbolFile/DWARF/LogChannelDWARF.cpp | 20 +- .../SymbolFile/DWARF/LogChannelDWARF.h | 29 +- .../SymbolFile/DWARF/ManualDWARFIndex.cpp | 320 ++- .../SymbolFile/DWARF/ManualDWARFIndex.h | 104 +- .../Plugins/SymbolFile/DWARF/NameToDIE.cpp | 77 +- .../Plugins/SymbolFile/DWARF/NameToDIE.h | 41 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 1423 ++++++---- .../SymbolFile/DWARF/SymbolFileDWARF.h | 120 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 235 +- .../DWARF/SymbolFileDWARFDebugMap.h | 54 +- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 27 +- .../SymbolFile/DWARF/SymbolFileDWARFDwo.h | 21 +- .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 2 + .../SymbolFile/NativePDB/CMakeLists.txt | 1 + .../NativePDB/CodeViewRegisterMapping.cpp | 291 ++ .../NativePDB/CodeViewRegisterMapping.h | 1 + .../SymbolFile/NativePDB/CompileUnitIndex.cpp | 23 +- .../SymbolFile/NativePDB/CompileUnitIndex.h | 19 +- .../NativePDB/DWARFLocationExpression.cpp | 102 +- .../NativePDB/DWARFLocationExpression.h | 12 + .../SymbolFile/NativePDB/PdbAstBuilder.cpp | 931 ++++--- .../SymbolFile/NativePDB/PdbAstBuilder.h | 38 +- .../PdbFPOProgramToDWARFExpression.cpp | 1 + .../Plugins/SymbolFile/NativePDB/PdbIndex.cpp | 34 +- .../Plugins/SymbolFile/NativePDB/PdbIndex.h | 10 +- .../Plugins/SymbolFile/NativePDB/PdbUtil.cpp | 389 ++- .../Plugins/SymbolFile/NativePDB/PdbUtil.h | 9 +- .../NativePDB/SymbolFileNativePDB.cpp | 1202 ++++++-- .../NativePDB/SymbolFileNativePDB.h | 71 +- .../NativePDB/UdtRecordCompleter.cpp | 268 +- .../SymbolFile/NativePDB/UdtRecordCompleter.h | 74 +- .../Plugins/SymbolFile/PDB/PDBASTParser.cpp | 123 +- .../PDB/PDBLocationToDWARFExpression.cpp | 3 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 170 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.h | 20 +- .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 23 +- .../SymbolFile/Symtab/SymbolFileSymtab.h | 15 +- .../Plugins/SymbolVendor/CMakeLists.txt | 4 +- .../SymbolVendor/ELF/SymbolVendorELF.cpp | 14 +- .../SymbolVendor/ELF/SymbolVendorELF.h | 8 +- .../MacOSX/SymbolVendorMacOSX.cpp | 48 +- .../SymbolVendor/MacOSX/SymbolVendorMacOSX.h | 8 +- .../SymbolVendor/PECOFF/CMakeLists.txt | 9 + .../PECOFF/SymbolVendorPECOFF.cpp | 136 + .../SymbolVendor/PECOFF/SymbolVendorPECOFF.h | 37 + .../SymbolVendor/wasm/SymbolVendorWasm.cpp | 15 +- .../SymbolVendor/wasm/SymbolVendorWasm.h | 7 +- .../MacOSX/AppleGetItemInfoHandler.cpp | 23 +- .../MacOSX/AppleGetPendingItemsHandler.cpp | 17 +- .../MacOSX/AppleGetQueuesHandler.cpp | 17 +- .../MacOSX/AppleGetThreadItemInfoHandler.cpp | 17 +- .../MacOSX/SystemRuntimeMacOSX.cpp | 79 +- .../MacOSX/SystemRuntimeMacOSX.h | 18 +- .../Plugins/Trace/common/CMakeLists.txt | 1 - .../Trace/common/ThreadPostMortemTrace.cpp | 4 +- .../Trace/common/ThreadPostMortemTrace.h | 9 +- .../Plugins/Trace/intel-pt/CMakeLists.txt | 23 +- .../CommandObjectTraceStartIntelPT.cpp | 106 +- .../intel-pt/CommandObjectTraceStartIntelPT.h | 40 +- .../Plugins/Trace/intel-pt/DecodedThread.cpp | 300 +- .../Plugins/Trace/intel-pt/DecodedThread.h | 338 ++- .../Plugins/Trace/intel-pt/LibiptDecoder.cpp | 783 ++++++ .../Plugins/Trace/intel-pt/LibiptDecoder.h | 125 + .../intel-pt/PerfContextSwitchDecoder.cpp | 332 +++ .../Trace/intel-pt/PerfContextSwitchDecoder.h | 148 + .../Plugins/Trace/intel-pt/TaskTimer.cpp | 32 + .../source/Plugins/Trace/intel-pt/TaskTimer.h | 78 + .../Plugins/Trace/intel-pt/ThreadDecoder.cpp | 67 + .../Plugins/Trace/intel-pt/ThreadDecoder.h | 59 + .../Trace/intel-pt/TraceCursorIntelPT.cpp | 164 +- .../Trace/intel-pt/TraceCursorIntelPT.h | 71 +- .../Plugins/Trace/intel-pt/TraceIntelPT.cpp | 682 ++++- .../Plugins/Trace/intel-pt/TraceIntelPT.h | 218 +- .../intel-pt/TraceIntelPTBundleLoader.cpp | 435 +++ .../Trace/intel-pt/TraceIntelPTBundleLoader.h | 130 + .../intel-pt/TraceIntelPTBundleSaver.cpp | 402 +++ .../Trace/intel-pt/TraceIntelPTBundleSaver.h | 48 + .../Trace/intel-pt/TraceIntelPTConstants.h | 17 +- .../intel-pt/TraceIntelPTJSONStructs.cpp | 189 ++ .../Trace/intel-pt/TraceIntelPTJSONStructs.h | 101 + .../intel-pt/TraceIntelPTMultiCpuDecoder.cpp | 238 ++ .../intel-pt/TraceIntelPTMultiCpuDecoder.h | 110 + .../Trace/intel-pt/TraceIntelPTOptions.td | 182 +- .../Trace/intel-pt/TraceIntelPTProperties.td | 24 + .../Trace/intel-pt/forward-declarations.h | 4 + .../Plugins/TraceExporter/CMakeLists.txt | 1 + .../TraceExporter/common/CMakeLists.txt | 7 + .../Plugins/TraceExporter/common/TraceHTR.cpp | 491 ++++ .../Plugins/TraceExporter/common/TraceHTR.h | 409 +++ .../Plugins/TraceExporter/ctf/CMakeLists.txt | 1 + .../ctf/CommandObjectThreadTraceExportCTF.cpp | 51 +- .../ctf/CommandObjectThreadTraceExportCTF.h | 7 +- .../TraceExporter/ctf/TraceExporterCTF.cpp | 9 - .../TraceExporter/ctf/TraceExporterCTF.h | 8 +- .../ctf/TraceExporterCTFOptions.td | 4 + .../source/Plugins/TraceExporter/docs/htr.rst | 48 + .../TypeSystem/Clang/TypeSystemClang.cpp | 908 +++--- .../TypeSystem/Clang/TypeSystemClang.h | 159 +- .../UnwindAssemblyInstEmulation.cpp | 83 +- .../UnwindAssemblyInstEmulation.h | 14 +- .../UnwindAssembly/x86/UnwindAssembly-x86.cpp | 15 +- .../UnwindAssembly/x86/UnwindAssembly-x86.h | 8 +- gnu/llvm/lldb/source/Symbol/ArmUnwindInfo.cpp | 6 +- gnu/llvm/lldb/source/Symbol/Block.cpp | 13 +- gnu/llvm/lldb/source/Symbol/CMakeLists.txt | 6 +- .../lldb/source/Symbol/CompactUnwindInfo.cpp | 18 +- gnu/llvm/lldb/source/Symbol/CompileUnit.cpp | 90 +- gnu/llvm/lldb/source/Symbol/CompilerType.cpp | 456 +-- .../lldb/source/Symbol/DWARFCallFrameInfo.cpp | 65 +- gnu/llvm/lldb/source/Symbol/DeclVendor.cpp | 2 - gnu/llvm/lldb/source/Symbol/Function.cpp | 35 +- .../lldb/source/Symbol/LocateSymbolFile.cpp | 84 +- .../source/Symbol/LocateSymbolFileMacOSX.cpp | 522 ++-- .../lldb/source/Symbol/ObjectContainer.cpp | 59 + gnu/llvm/lldb/source/Symbol/ObjectFile.cpp | 80 +- .../lldb/source/Symbol/PostfixExpression.cpp | 12 +- gnu/llvm/lldb/source/Symbol/Symbol.cpp | 163 +- gnu/llvm/lldb/source/Symbol/SymbolContext.cpp | 47 +- gnu/llvm/lldb/source/Symbol/SymbolFile.cpp | 127 +- .../lldb/source/Symbol/SymbolFileOnDemand.cpp | 602 ++++ gnu/llvm/lldb/source/Symbol/SymbolVendor.cpp | 8 - gnu/llvm/lldb/source/Symbol/Symtab.cpp | 260 +- gnu/llvm/lldb/source/Symbol/Type.cpp | 64 +- gnu/llvm/lldb/source/Symbol/TypeList.cpp | 15 +- gnu/llvm/lldb/source/Symbol/TypeMap.cpp | 41 +- gnu/llvm/lldb/source/Symbol/TypeSystem.cpp | 104 +- gnu/llvm/lldb/source/Symbol/UnwindPlan.cpp | 25 +- gnu/llvm/lldb/source/Symbol/UnwindTable.cpp | 7 +- gnu/llvm/lldb/source/Symbol/Variable.cpp | 92 +- gnu/llvm/lldb/source/Target/ABI.cpp | 61 +- .../source/Target/AssertFrameRecognizer.cpp | 13 +- gnu/llvm/lldb/source/Target/CMakeLists.txt | 5 +- .../source/Target/DynamicRegisterInfo.cpp | 820 ++++++ .../lldb/source/Target/ExecutionContext.cpp | 18 +- gnu/llvm/lldb/source/Target/JITLoaderList.cpp | 4 +- gnu/llvm/lldb/source/Target/Language.cpp | 40 +- .../lldb/source/Target/LanguageRuntime.cpp | 5 +- gnu/llvm/lldb/source/Target/Memory.cpp | 17 +- gnu/llvm/lldb/source/Target/MemoryTagMap.cpp | 65 + gnu/llvm/lldb/source/Target/ModuleCache.cpp | 5 +- .../lldb/source/Target/OperatingSystem.cpp | 3 +- .../lldb/source/Target/PathMappingList.cpp | 106 +- gnu/llvm/lldb/source/Target/Platform.cpp | 780 +++--- gnu/llvm/lldb/source/Target/Process.cpp | 772 +++--- gnu/llvm/lldb/source/Target/ProcessTrace.cpp | 17 +- .../lldb/source/Target/RegisterContext.cpp | 104 +- .../source/Target/RegisterContextUnwind.cpp | 138 +- .../source/Target/RemoteAwarePlatform.cpp | 119 +- .../lldb/source/Target/SectionLoadList.cpp | 23 +- gnu/llvm/lldb/source/Target/StackFrame.cpp | 137 +- .../lldb/source/Target/StackFrameList.cpp | 11 +- .../source/Target/StackFrameRecognizer.cpp | 2 +- gnu/llvm/lldb/source/Target/Statistics.cpp | 315 +++ gnu/llvm/lldb/source/Target/StopInfo.cpp | 585 ++-- gnu/llvm/lldb/source/Target/Target.cpp | 827 ++++-- gnu/llvm/lldb/source/Target/TargetList.cpp | 123 +- .../lldb/source/Target/TargetProperties.td | 27 +- gnu/llvm/lldb/source/Target/Thread.cpp | 140 +- .../lldb/source/Target/ThreadCollection.cpp | 8 +- gnu/llvm/lldb/source/Target/ThreadList.cpp | 82 +- gnu/llvm/lldb/source/Target/ThreadPlan.cpp | 25 +- .../lldb/source/Target/ThreadPlanBase.cpp | 9 +- .../source/Target/ThreadPlanCallFunction.cpp | 28 +- .../Target/ThreadPlanCallOnFunctionExit.cpp | 2 +- .../Target/ThreadPlanCallUserExpression.cpp | 10 +- .../lldb/source/Target/ThreadPlanPython.cpp | 22 +- .../source/Target/ThreadPlanRunToAddress.cpp | 3 +- .../Target/ThreadPlanShouldStopHere.cpp | 7 +- .../lldb/source/Target/ThreadPlanStack.cpp | 47 +- .../source/Target/ThreadPlanStepInRange.cpp | 27 +- .../Target/ThreadPlanStepInstruction.cpp | 8 +- .../lldb/source/Target/ThreadPlanStepOut.cpp | 7 +- .../Target/ThreadPlanStepOverBreakpoint.cpp | 9 +- .../source/Target/ThreadPlanStepOverRange.cpp | 7 +- .../source/Target/ThreadPlanStepRange.cpp | 15 +- .../source/Target/ThreadPlanStepThrough.cpp | 9 +- .../source/Target/ThreadPlanStepUntil.cpp | 3 +- .../lldb/source/Target/ThreadPlanTracer.cpp | 24 +- gnu/llvm/lldb/source/Target/Trace.cpp | 503 +++- gnu/llvm/lldb/source/Target/TraceCursor.cpp | 38 +- gnu/llvm/lldb/source/Target/TraceDumper.cpp | 913 ++++++ gnu/llvm/lldb/source/Target/TraceExporter.cpp | 5 +- gnu/llvm/lldb/source/Target/UnwindLLDB.cpp | 8 +- gnu/llvm/lldb/source/Utility/Args.cpp | 33 +- gnu/llvm/lldb/source/Utility/Broadcaster.cpp | 18 +- gnu/llvm/lldb/source/Utility/CMakeLists.txt | 9 +- gnu/llvm/lldb/source/Utility/ConstString.cpp | 30 +- .../lldb/source/Utility/DataBufferHeap.cpp | 20 +- .../lldb/source/Utility/DataBufferLLVM.cpp | 27 +- gnu/llvm/lldb/source/Utility/DataEncoder.cpp | 161 +- .../lldb/source/Utility/DataExtractor.cpp | 10 +- gnu/llvm/lldb/source/Utility/Diagnostics.cpp | 107 + gnu/llvm/lldb/source/Utility/Environment.cpp | 2 +- gnu/llvm/lldb/source/Utility/Event.cpp | 4 +- gnu/llvm/lldb/source/Utility/FileSpec.cpp | 98 +- gnu/llvm/lldb/source/Utility/GDBRemote.cpp | 97 - .../lldb/source/Utility/Instrumentation.cpp | 44 + gnu/llvm/lldb/source/Utility/LLDBLog.cpp | 82 + gnu/llvm/lldb/source/Utility/Listener.cpp | 26 +- gnu/llvm/lldb/source/Utility/Log.cpp | 168 +- .../Utility/LoongArch_DWARF_Registers.h | 177 ++ gnu/llvm/lldb/source/Utility/ProcessInfo.cpp | 59 +- .../source/Utility/RISCV_DWARF_Registers.h | 195 ++ .../lldb/source/Utility/RegisterValue.cpp | 67 +- gnu/llvm/lldb/source/Utility/Scalar.cpp | 2 +- gnu/llvm/lldb/source/Utility/SelectHelper.cpp | 34 +- gnu/llvm/lldb/source/Utility/Status.cpp | 7 +- gnu/llvm/lldb/source/Utility/Stream.cpp | 11 +- .../lldb/source/Utility/StringExtractor.cpp | 6 +- .../Utility/StringExtractorGDBRemote.cpp | 34 +- gnu/llvm/lldb/source/Utility/StringList.cpp | 14 +- .../lldb/source/Utility/StructuredData.cpp | 103 + gnu/llvm/lldb/source/Utility/Timer.cpp | 11 +- .../source/Utility/TraceGDBRemotePackets.cpp | 52 +- .../Utility/TraceIntelPTGDBRemotePackets.cpp | 113 +- gnu/llvm/lldb/source/Utility/UUID.cpp | 19 +- gnu/llvm/lldb/source/Utility/UriParser.cpp | 44 +- .../lldb/source/Utility/UserIDResolver.cpp | 17 +- .../lldb/source/Utility/UuidCompatibility.h | 8 + gnu/llvm/lldb/source/Utility/VMRange.cpp | 10 +- gnu/llvm/lldb/source/Utility/XcodeSDK.cpp | 5 +- gnu/llvm/lldb/source/Version/CMakeLists.txt | 42 + gnu/llvm/lldb/source/Version/Version.cpp | 73 + .../module/pexpect-4.6/pexpect/spawnbase.py | 2 +- .../Python/module/progress/progress.py | 25 +- .../ptyprocess-0.6.0/ptyprocess/ptyprocess.py | 2 +- .../Python/module/unittest2/unittest2/case.py | 21 +- .../Python/module/unittest2/unittest2/main.py | 3 +- .../module/unittest2/unittest2/result.py | 7 +- .../module/unittest2/unittest2/suite.py | 3 +- .../unittest2/unittest2/test/test_case.py | 3 +- .../unittest2/test/test_functiontestcase.py | 3 +- .../compact-unwind/compact-unwind-dumper.c | 43 - .../lldb/tools/debugserver/CMakeLists.txt | 12 + .../debugserver.xcodeproj/project.pbxproj | 2 +- .../tools/debugserver/source/CMakeLists.txt | 31 +- .../lldb/tools/debugserver/source/DNB.cpp | 56 +- gnu/llvm/lldb/tools/debugserver/source/DNB.h | 23 +- .../debugserver/source/DNBBreakpoint.cpp | 6 +- .../tools/debugserver/source/DNBDataRef.cpp | 2 +- .../lldb/tools/debugserver/source/DNBDefs.h | 6 +- .../lldb/tools/debugserver/source/DNBTimer.h | 2 +- .../lldb/tools/debugserver/source/JSON.cpp | 4 +- gnu/llvm/lldb/tools/debugserver/source/JSON.h | 2 +- .../tools/debugserver/source/JSONGenerator.h | 85 +- .../debugserver/source/MacOSX/CFBundle.cpp | 5 +- .../debugserver/source/MacOSX/CFString.cpp | 4 +- .../debugserver/source/MacOSX/CMakeLists.txt | 30 +- .../debugserver/source/MacOSX/Genealogy.cpp | 2 +- .../source/MacOSX/MachException.cpp | 47 + .../debugserver/source/MacOSX/MachException.h | 1 + .../debugserver/source/MacOSX/MachProcess.h | 21 +- .../debugserver/source/MacOSX/MachProcess.mm | 336 ++- .../debugserver/source/MacOSX/MachTask.h | 5 +- .../debugserver/source/MacOSX/MachTask.mm | 18 +- .../source/MacOSX/MachThreadList.cpp | 2 +- .../source/MacOSX/MachVMMemory.cpp | 3 +- .../source/MacOSX/MachVMRegion.cpp | 42 +- .../debugserver/source/MacOSX/MachVMRegion.h | 1 + .../source/MacOSX/arm/DNBArchImpl.cpp | 4 +- .../source/MacOSX/arm64/DNBArchImplARM64.cpp | 107 +- .../MacOSX/x86_64/DNBArchImplX86_64.cpp | 12 +- .../tools/debugserver/source/RNBContext.cpp | 15 + .../tools/debugserver/source/RNBContext.h | 12 +- .../tools/debugserver/source/RNBRemote.cpp | 173 +- .../lldb/tools/debugserver/source/RNBRemote.h | 4 + .../debugserver/source/StdStringExtractor.cpp | 2 +- .../debugserver/source/StringConvert.cpp | 62 + .../tools/debugserver/source/StringConvert.h | 27 + .../tools/debugserver/source/TTYState.cpp | 11 +- .../tools/debugserver/source/debugserver.cpp | 6 +- gnu/llvm/lldb/tools/driver/CMakeLists.txt | 4 - gnu/llvm/lldb/tools/driver/Driver.h | 1 + gnu/llvm/lldb/tools/driver/Options.td | 25 +- gnu/llvm/lldb/tools/driver/Platform.h | 7 +- .../intel-features/intel-mpx/CMakeLists.txt | 1 + .../intel-mpx/cli-wrapper-mpxtable.cpp | 2 +- .../intel-mpx/test/TestMPXTable.py | 2 - .../lldb/tools/lldb-fuzzer/CMakeLists.txt | 4 + .../CMakeLists.txt | 32 + .../inputdictionary.txt | 4 + .../lldb-commandinterpreter-fuzzer.cpp | 47 + .../lldb-expression-fuzzer/CMakeLists.txt | 60 + .../lldb-expression-fuzzer.cpp | 109 + .../lldb-target-fuzzer/CMakeLists.txt | 28 + .../lldb-target-fuzzer/lldb-target-fuzzer.cpp | 35 + .../tools/lldb-fuzzer/utils/CMakeLists.txt | 6 + .../lldb/tools/lldb-fuzzer/utils/TempFile.cpp | 33 + .../lldb/tools/lldb-fuzzer/utils/TempFile.h | 27 + gnu/llvm/lldb/tools/lldb-instr/CMakeLists.txt | 2 - gnu/llvm/lldb/tools/lldb-instr/Instrument.cpp | 236 +- gnu/llvm/lldb/tools/lldb-server/Acceptor.cpp | 16 +- .../tools/lldb-server/LLDBServerUtilities.cpp | 24 +- .../lldb-server/SystemInitializerLLGS.cpp | 22 + .../lldb/tools/lldb-server/lldb-platform.cpp | 38 +- .../lldb/tools/lldb-server/lldb-server.cpp | 2 +- gnu/llvm/lldb/tools/lldb-test/CMakeLists.txt | 3 +- gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp | 124 +- .../lldb/tools/lldb-vscode/BreakpointBase.cpp | 290 ++ .../lldb/tools/lldb-vscode/BreakpointBase.h | 21 +- .../lldb/tools/lldb-vscode/CMakeLists.txt | 2 - gnu/llvm/lldb/tools/lldb-vscode/FifoFiles.cpp | 20 +- gnu/llvm/lldb/tools/lldb-vscode/FifoFiles.h | 2 + .../tools/lldb-vscode/FunctionBreakpoint.cpp | 2 + gnu/llvm/lldb/tools/lldb-vscode/IOStream.cpp | 2 +- gnu/llvm/lldb/tools/lldb-vscode/JSONUtils.cpp | 179 +- gnu/llvm/lldb/tools/lldb-vscode/JSONUtils.h | 18 +- .../tools/lldb-vscode/OutputRedirector.cpp | 14 +- .../lldb/tools/lldb-vscode/ProgressEvent.cpp | 27 +- .../lldb/tools/lldb-vscode/ProgressEvent.h | 14 +- gnu/llvm/lldb/tools/lldb-vscode/README.md | 8 + .../lldb/tools/lldb-vscode/RunInTerminal.cpp | 6 +- .../tools/lldb-vscode/SourceBreakpoint.cpp | 2 + gnu/llvm/lldb/tools/lldb-vscode/VSCode.cpp | 103 +- gnu/llvm/lldb/tools/lldb-vscode/VSCode.h | 73 +- .../lldb/tools/lldb-vscode/lldb-vscode.cpp | 333 ++- gnu/llvm/lldb/tools/lldb-vscode/package.json | 10 +- .../utils/TableGen/LLDBOptionDefEmitter.cpp | 8 +- gnu/llvm/lldb/utils/lit-cpuid/CMakeLists.txt | 5 +- .../lldb/utils/lldb-dotest/CMakeLists.txt | 24 +- .../lldb/utils/lldb-dotest/lldb-dotest.in | 15 +- 1701 files changed, 91188 insertions(+), 48340 deletions(-) create mode 100644 gnu/llvm/lldb/bindings/interface/SBTraceCursor.i create mode 100755 gnu/llvm/lldb/bindings/python/get-python-config.py create mode 100755 gnu/llvm/lldb/bindings/python/lldb-python create mode 100644 gnu/llvm/lldb/docs/resources/fuzzing.rst create mode 100644 gnu/llvm/lldb/docs/use/extensions.rst create mode 100644 gnu/llvm/lldb/docs/use/intel_pt.rst create mode 100644 gnu/llvm/lldb/docs/use/links.rst create mode 100644 gnu/llvm/lldb/docs/use/ondemand.rst create mode 100644 gnu/llvm/lldb/examples/python/scripted_process/crashlog_scripted_process.py create mode 100644 gnu/llvm/lldb/examples/python/scripted_process/scripted_platform.py create mode 100644 gnu/llvm/lldb/examples/synthetic/recognizer_function/example.py create mode 100644 gnu/llvm/lldb/examples/synthetic/recognizer_function/lldb-commands create mode 100644 gnu/llvm/lldb/examples/synthetic/recognizer_function/program.cpp create mode 100644 gnu/llvm/lldb/include/lldb/API/SBTraceCursor.h create mode 100644 gnu/llvm/lldb/include/lldb/Core/DataFileCache.h create mode 100644 gnu/llvm/lldb/include/lldb/Core/DebuggerEvents.h create mode 100644 gnu/llvm/lldb/include/lldb/Core/ThreadedCommunication.h create mode 100644 gnu/llvm/lldb/include/lldb/Expression/DWARFExpressionList.h create mode 100644 gnu/llvm/lldb/include/lldb/Host/posix/MainLoopPosix.h create mode 100644 gnu/llvm/lldb/include/lldb/Host/windows/MainLoopWindows.h create mode 100644 gnu/llvm/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h create mode 100644 gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h create mode 100644 gnu/llvm/lldb/include/lldb/Interpreter/ScriptedInterface.h create mode 100644 gnu/llvm/lldb/include/lldb/Interpreter/ScriptedMetadata.h create mode 100644 gnu/llvm/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h create mode 100644 gnu/llvm/lldb/include/lldb/Symbol/SymbolFileOnDemand.h create mode 100644 gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.def create mode 100644 gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.h create mode 100644 gnu/llvm/lldb/include/lldb/Target/DynamicRegisterInfo.h create mode 100644 gnu/llvm/lldb/include/lldb/Target/MemoryTagMap.h create mode 100644 gnu/llvm/lldb/include/lldb/Target/Statistics.h create mode 100644 gnu/llvm/lldb/include/lldb/Target/TraceDumper.h create mode 100644 gnu/llvm/lldb/include/lldb/Utility/Diagnostics.h create mode 100644 gnu/llvm/lldb/include/lldb/Utility/Instrumentation.h create mode 100644 gnu/llvm/lldb/include/lldb/Utility/LLDBLog.h create mode 100644 gnu/llvm/lldb/include/lldb/Version/Version.h create mode 100644 gnu/llvm/lldb/include/lldb/Version/Version.inc.in create mode 100644 gnu/llvm/lldb/packages/Python/lldbsuite/test/gdbclientutils.py create mode 100644 gnu/llvm/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py create mode 100644 gnu/llvm/lldb/packages/Python/lldbsuite/test/tools/lldb-server/fork_testbase.py create mode 100644 gnu/llvm/lldb/source/API/SBTraceCursor.cpp create mode 100644 gnu/llvm/lldb/source/Commands/CommandObjectDWIMPrint.cpp create mode 100644 gnu/llvm/lldb/source/Commands/CommandObjectDWIMPrint.h create mode 100644 gnu/llvm/lldb/source/Commands/CommandObjectDiagnostics.cpp create mode 100644 gnu/llvm/lldb/source/Commands/CommandObjectDiagnostics.h create mode 100644 gnu/llvm/lldb/source/Commands/CommandOptionArgumentTable.cpp create mode 100644 gnu/llvm/lldb/source/Core/DataFileCache.cpp create mode 100644 gnu/llvm/lldb/source/Core/DebuggerEvents.cpp create mode 100644 gnu/llvm/lldb/source/Core/ThreadedCommunication.cpp create mode 100644 gnu/llvm/lldb/source/Expression/DWARFExpressionList.cpp create mode 100644 gnu/llvm/lldb/source/Host/common/MainLoopBase.cpp create mode 100644 gnu/llvm/lldb/source/Host/posix/MainLoopPosix.cpp create mode 100644 gnu/llvm/lldb/source/Host/windows/MainLoopWindows.cpp create mode 100644 gnu/llvm/lldb/source/Interpreter/OptionGroupMemoryTag.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ABI/X86/ABIX86_i386.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ABI/X86/ABIX86_i386.h create mode 100644 gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/LoongArch/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/RISCV/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.h create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h create mode 100644 gnu/llvm/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/Coroutines.h create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/Generic.h create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Language/ObjC/ObjCConstants.h create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/Minidump/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h create mode 100644 gnu/llvm/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/QemuUser/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUser.h create mode 100644 gnu/llvm/lldb/source/Plugins/Platform/QemuUser/PlatformQemuUserProperties.td create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTCollector.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTProcessTrace.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_riscv64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_riscv64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/Perf.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/Perf.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Linux/Procfs.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/RegisterInfos_riscv64.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/Utility/lldb-riscv-register-enums.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteErrno.def create mode 100644 gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.h create mode 100644 gnu/llvm/lldb/source/Plugins/Process/scripted/ScriptedThread.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Process/scripted/ScriptedThread.h create mode 100644 gnu/llvm/lldb/source/Plugins/REPL/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/REPL/Clang/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/REPL/Clang/ClangREPL.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/REPL/Clang/ClangREPL.h create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h create mode 100644 gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/SymbolVendor/PECOFF/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/SymbolVendor/PECOFF/SymbolVendorPECOFF.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/LibiptDecoder.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TaskTimer.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TaskTimer.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/ThreadDecoder.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleLoader.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTBundleSaver.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h create mode 100644 gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTProperties.td create mode 100644 gnu/llvm/lldb/source/Plugins/TraceExporter/common/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Plugins/TraceExporter/common/TraceHTR.cpp create mode 100644 gnu/llvm/lldb/source/Plugins/TraceExporter/common/TraceHTR.h create mode 100644 gnu/llvm/lldb/source/Plugins/TraceExporter/docs/htr.rst create mode 100644 gnu/llvm/lldb/source/Symbol/ObjectContainer.cpp create mode 100644 gnu/llvm/lldb/source/Symbol/SymbolFileOnDemand.cpp create mode 100644 gnu/llvm/lldb/source/Target/DynamicRegisterInfo.cpp create mode 100644 gnu/llvm/lldb/source/Target/MemoryTagMap.cpp create mode 100644 gnu/llvm/lldb/source/Target/Statistics.cpp create mode 100644 gnu/llvm/lldb/source/Target/TraceDumper.cpp create mode 100644 gnu/llvm/lldb/source/Utility/Diagnostics.cpp create mode 100644 gnu/llvm/lldb/source/Utility/Instrumentation.cpp create mode 100644 gnu/llvm/lldb/source/Utility/LLDBLog.cpp create mode 100644 gnu/llvm/lldb/source/Utility/LoongArch_DWARF_Registers.h create mode 100644 gnu/llvm/lldb/source/Utility/RISCV_DWARF_Registers.h create mode 100644 gnu/llvm/lldb/source/Version/CMakeLists.txt create mode 100644 gnu/llvm/lldb/source/Version/Version.cpp create mode 100644 gnu/llvm/lldb/tools/debugserver/source/StringConvert.cpp create mode 100644 gnu/llvm/lldb/tools/debugserver/source/StringConvert.h create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/CMakeLists.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-commandinterpreter-fuzzer/CMakeLists.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-commandinterpreter-fuzzer/inputdictionary.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-commandinterpreter-fuzzer/lldb-commandinterpreter-fuzzer.cpp create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-expression-fuzzer/CMakeLists.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-expression-fuzzer/lldb-expression-fuzzer.cpp create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-target-fuzzer/CMakeLists.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/lldb-target-fuzzer/lldb-target-fuzzer.cpp create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/utils/CMakeLists.txt create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/utils/TempFile.cpp create mode 100644 gnu/llvm/lldb/tools/lldb-fuzzer/utils/TempFile.h diff --git a/gnu/llvm/lldb/.clang-tidy b/gnu/llvm/lldb/.clang-tidy index 2cde63668d0..499170a49c0 100644 --- a/gnu/llvm/lldb/.clang-tidy +++ b/gnu/llvm/lldb/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '-readability-identifier-naming,modernize-use-default-member-init,modernize-use-equals-default' +Checks: '-readability-identifier-naming,modernize-use-default-member-init,modernize-use-equals-default,modernize-use-override' InheritParentConfig: true CheckOptions: - key: modernize-use-default-member-init.IgnoreMacros diff --git a/gnu/llvm/lldb/CMakeLists.txt b/gnu/llvm/lldb/CMakeLists.txt index 2bb05c1e220..20d584c48ba 100644 --- a/gnu/llvm/lldb/CMakeLists.txt +++ b/gnu/llvm/lldb/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13.4) +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + # Add path for custom modules. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} @@ -11,9 +17,26 @@ set(CMAKE_MODULE_PATH # using LLVM as an external library. if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(lldb) + set(LLDB_BUILT_STANDALONE TRUE) + set(LLVM_INCLUDE_TESTS ON CACHE INTERNAL "") + if ("${CMAKE_VERSION}" VERSION_LESS "3.20.0") + message(WARNING + "Your CMake version is ${CMAKE_VERSION}. Starting with LLVM 17.0.0, the " + "minimum version of CMake required to build LLVM will become 3.20.0, and " + "using an older CMake will become an error. Please upgrade your CMake to " + "at least 3.20.0 now to avoid issues in the future!") + endif() +endif() + +# Must go below project(..) +include(GNUInstallDirs) + +option(LLDB_INCLUDE_TESTS "Generate build targets for the LLDB unit tests." ${LLVM_INCLUDE_TESTS}) + +if(LLDB_BUILT_STANDALONE) include(LLDBStandalone) - set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ standard to conform to") + set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) endif() @@ -31,24 +54,37 @@ if (WIN32) endif() if (LLDB_ENABLE_PYTHON) - if (NOT CMAKE_CROSSCOMPILING) - execute_process( - COMMAND ${Python3_EXECUTABLE} - -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))" - OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE) - - file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH) - else () - if ("${LLDB_PYTHON_RELATIVE_PATH}" STREQUAL "") - message(FATAL_ERROR - "Crosscompiling LLDB with Python requires manually setting - LLDB_PYTHON_RELATIVE_PATH.") - endif () - endif () - - set(LLDB_PYTHON_RELATIVE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} - CACHE STRING "Path where Python modules are installed, relative to install prefix") + set(cachestring_LLDB_PYTHON_RELATIVE_PATH + "Path where Python modules are installed, relative to LLDB's install prefix") + set(cachestring_LLDB_PYTHON_EXE_RELATIVE_PATH + "Path to python interpreter exectuable, relative to python's install prefix") + set(cachestring_LLDB_PYTHON_EXT_SUFFIX + "Filename extension for native code python modules") + + foreach(var LLDB_PYTHON_RELATIVE_PATH LLDB_PYTHON_EXE_RELATIVE_PATH LLDB_PYTHON_EXT_SUFFIX) + if(NOT DEFINED ${var} AND NOT CMAKE_CROSSCOMPILING) + execute_process( + COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/get-python-config.py + ${var} + OUTPUT_VARIABLE value + OUTPUT_STRIP_TRAILING_WHITESPACE) + file(TO_CMAKE_PATH "${value}" value) + set(${var} ${value} CACHE STRING ${cachestring_${var}}) + else() + if ("${${var}}" STREQUAL "") + message(FATAL_ERROR + "Crosscompiling LLDB with Python requires manually setting ${var}.") + endif() + endif() + endforeach() +endif () + +if (LLDB_ENABLE_LUA) + find_program(Lua_EXECUTABLE lua5.3) + set(LLDB_LUA_DEFAULT_RELATIVE_PATH "lib/lua/5.3") + set(LLDB_LUA_RELATIVE_PATH ${LLDB_LUA_DEFAULT_RELATIVE_PATH} + CACHE STRING "Path where Lua modules are installed, relative to install prefix") endif () if (LLDB_ENABLE_PYTHON OR LLDB_ENABLE_LUA) @@ -64,7 +100,7 @@ if(LLVM_ENABLE_MODULES) list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen) endif() -if(CMAKE_CROSSCOMPILING AND LLDB_BUILT_STANDALONE) +if(CMAKE_CROSSCOMPILING AND LLDB_BUILT_STANDALONE AND NOT LLDB_TABLEGEN_EXE) set(LLVM_USE_HOST_TOOLS ON) include(CrossCompile) if (NOT NATIVE_LLVM_DIR OR NOT NATIVE_Clang_DIR) @@ -94,10 +130,26 @@ if (LLDB_ENABLE_PYTHON) finish_swig_python("lldb-python" "${lldb_python_bindings_dir}" "${lldb_python_target_dir}") endif() -option(LLDB_INCLUDE_TESTS "Generate build targets for the LLDB unit tests." ${LLVM_INCLUDE_TESTS}) +if (LLDB_ENABLE_LUA) + if(LLDB_BUILD_FRAMEWORK) + set(lldb_lua_target_dir "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/Resources/Lua") + else() + set(lldb_lua_target_dir "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${LLDB_LUA_RELATIVE_PATH}") + endif() + get_target_property(lldb_lua_bindings_dir swig_wrapper_lua BINARY_DIR) + finish_swig_lua("lldb-lua" "${lldb_lua_bindings_dir}" "${lldb_lua_target_dir}") +endif() + +set(LLDB_INCLUDE_UNITTESTS ON) +if (NOT TARGET llvm_gtest) + set(LLDB_INCLUDE_UNITTESTS OFF) +endif() + if(LLDB_INCLUDE_TESTS) add_subdirectory(test) - add_subdirectory(unittests) + if (LLDB_INCLUDE_UNITTESTS) + add_subdirectory(unittests) + endif() add_subdirectory(utils) endif() diff --git a/gnu/llvm/lldb/CODE_OWNERS.txt b/gnu/llvm/lldb/CODE_OWNERS.txt index 1af1061c545..ae679e90d92 100644 --- a/gnu/llvm/lldb/CODE_OWNERS.txt +++ b/gnu/llvm/lldb/CODE_OWNERS.txt @@ -10,7 +10,7 @@ beautification by scripts. The fields are: name (N), email (E), web-address N: Greg Clayton E: clayborg@gmail.com -D: Overall LLDB architecture, Host (common+macosx), Symbol, API, ABI, Mac-specific code, +D: Overall LLDB architecture, Host (common+macosx), Symbol, API, ABI, Mac-specific code, D: DynamicLoader, ObjectFile, IOHandler, EditLine, Core/Value*, Watchpoints, debugserver D: Build scripts, Test suite, Platform, gdb-remote, Anything not covered by this file @@ -27,7 +27,7 @@ D: FreeBSD N: Jason Molenda E: jmolenda@apple.com -D: ABI, Disassembler, Unwinding, iOS, debugserver, Platform, ObjectFile, SymbolFile, +D: ABI, Disassembler, Unwinding, iOS, debugserver, Platform, ObjectFile, SymbolFile, D: SymbolVendor, DWARF, gdb-remote N: Kamil Rytarowski @@ -42,3 +42,8 @@ D: Test suite N: Pavel Labath E: labath@google.com D: Linux, Android + +N: Walter Erquinigo +E: a20012251@gmail.com +E: waltermelon@fb.com +D: Trace, TraceCursor, TraceExport, intel-pt, lldb-vscode, Data Formatters diff --git a/gnu/llvm/lldb/bindings/CMakeLists.txt b/gnu/llvm/lldb/bindings/CMakeLists.txt index 9759b069fdc..9eed2f1e629 100644 --- a/gnu/llvm/lldb/bindings/CMakeLists.txt +++ b/gnu/llvm/lldb/bindings/CMakeLists.txt @@ -26,11 +26,23 @@ set(SWIG_COMMON_FLAGS -features autodoc -I${LLDB_SOURCE_DIR}/include -I${CMAKE_CURRENT_SOURCE_DIR} - -D__STDC_LIMIT_MACROS - -D__STDC_CONSTANT_MACROS ${DARWIN_EXTRAS} ) +function(create_relative_symlink swig_target dest_file output_dir output_name) + get_filename_component(dest_file ${dest_file} ABSOLUTE) + get_filename_component(output_dir ${output_dir} ABSOLUTE) + file(RELATIVE_PATH rel_dest_file ${output_dir} ${dest_file}) + if(CMAKE_HOST_UNIX) + set(LLVM_LINK_OR_COPY create_symlink) + else() + set(LLVM_LINK_OR_COPY copy) + endif() + add_custom_command(TARGET ${swig_target} POST_BUILD VERBATIM + COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} ${rel_dest_file} ${output_name} + WORKING_DIRECTORY ${output_dir}) +endfunction() + if (LLDB_ENABLE_PYTHON) add_subdirectory(python) endif() diff --git a/gnu/llvm/lldb/bindings/interface/SBCommandInterpreter.i b/gnu/llvm/lldb/bindings/interface/SBCommandInterpreter.i index b9a32716cfd..cad79248d0a 100644 --- a/gnu/llvm/lldb/bindings/interface/SBCommandInterpreter.i +++ b/gnu/llvm/lldb/bindings/interface/SBCommandInterpreter.i @@ -125,6 +125,9 @@ public: bool HasAliasOptions (); + bool + IsInteractive (); + lldb::SBProcess GetProcess (); diff --git a/gnu/llvm/lldb/bindings/interface/SBCompileUnit.i b/gnu/llvm/lldb/bindings/interface/SBCompileUnit.i index 4c8efaedb7d..5a03069b4e0 100644 --- a/gnu/llvm/lldb/bindings/interface/SBCompileUnit.i +++ b/gnu/llvm/lldb/bindings/interface/SBCompileUnit.i @@ -67,6 +67,22 @@ public: lldb::SBLineEntry GetLineEntryAtIndex (uint32_t idx) const; + %feature("docstring", " + Get the index for a provided line entry in this compile unit. + + @param[in] line_entry + The SBLineEntry object for which we are looking for the index. + + @param[in] exact + An optional boolean defaulting to false that ensures that the provided + line entry has a perfect match in the compile unit. + + @return + The index of the user-provided line entry. UINT32_MAX if the line entry + was not found in the compile unit.") FindLineEntryIndex; + uint32_t + FindLineEntryIndex (lldb::SBLineEntry &line_entry, bool exact = false) const; + uint32_t FindLineEntryIndex (uint32_t start_idx, uint32_t line, diff --git a/gnu/llvm/lldb/bindings/interface/SBData.i b/gnu/llvm/lldb/bindings/interface/SBData.i index a1fb4472cd2..8e1d2fcf9d3 100644 --- a/gnu/llvm/lldb/bindings/interface/SBData.i +++ b/gnu/llvm/lldb/bindings/interface/SBData.i @@ -96,6 +96,10 @@ public: void SetData (lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + void + SetDataWithOwnership (lldb::SBError& error, const void *buf, size_t size, + lldb::ByteOrder endian, uint8_t addr_size); + bool Append (const SBData& rhs); @@ -153,7 +157,7 @@ public: for x in range(*key.indices(self.__len__())): list.append(self.__getitem__(x)) return list - if not (isinstance(key,six.integer_types)): + if not (isinstance(key, int)): raise TypeError('must be int') key = key * self.item_size # SBData uses byte-based indexes, but we want to use itemsize-based indexes here error = SBError() diff --git a/gnu/llvm/lldb/bindings/interface/SBDebugger.i b/gnu/llvm/lldb/bindings/interface/SBDebugger.i index cf4411980cc..e82ce2aa8e7 100644 --- a/gnu/llvm/lldb/bindings/interface/SBDebugger.i +++ b/gnu/llvm/lldb/bindings/interface/SBDebugger.i @@ -117,6 +117,23 @@ or the equivalent arguments for :py:class:`SBTarget.AttachToProcessWithID` .") S class SBDebugger { public: + enum + { + eBroadcastBitProgress = (1 << 0), + eBroadcastBitWarning = (1 << 1), + eBroadcastBitError = (1 << 2), + }; + + + static const char *GetProgressFromEvent(const lldb::SBEvent &event, + uint64_t &OUTPUT, + uint64_t &OUTPUT, + uint64_t &OUTPUT, + bool &OUTPUT); + + static lldb::SBStructuredData GetDiagnosticFromEvent(const lldb::SBEvent &event); + + SBBroadcaster GetBroadcaster(); static void Initialize(); @@ -124,6 +141,8 @@ public: static SBError InitializeWithErrorHandling(); + static void PrintStackTraceOnError(); + static void Terminate(); @@ -206,6 +225,11 @@ public: } } + lldb::SBStructuredData GetSetting(const char *setting = nullptr); + + SBError + SetInputString (const char* data); + SBError SetInputFile (SBFile file); @@ -479,6 +503,8 @@ public: lldb::SBTypeSynthetic GetSyntheticForType (lldb::SBTypeNameSpecifier); + SBStructuredData GetScriptInterpreterInfo(ScriptLanguage); + STRING_EXTENSION(SBDebugger) %feature("docstring", @@ -518,6 +544,8 @@ Example: :: lldb::SBError RunREPL (lldb::LanguageType language, const char *repl_options); + SBTrace LoadTraceFromFile(SBError &error, const SBFileSpec &trace_description_file); + #ifdef SWIGPYTHON %pythoncode%{ def __iter__(self): diff --git a/gnu/llvm/lldb/bindings/interface/SBFileSpec.i b/gnu/llvm/lldb/bindings/interface/SBFileSpec.i index b549321487e..e6f9bb81e24 100644 --- a/gnu/llvm/lldb/bindings/interface/SBFileSpec.i +++ b/gnu/llvm/lldb/bindings/interface/SBFileSpec.i @@ -84,18 +84,7 @@ public: #ifdef SWIGPYTHON %pythoncode %{ - def __get_fullpath__(self): - spec_dir = self.GetDirectory() - spec_file = self.GetFilename() - if spec_dir and spec_file: - return '%s/%s' % (spec_dir, spec_file) - elif spec_dir: - return spec_dir - elif spec_file: - return spec_file - return None - - fullpath = property(__get_fullpath__, None, doc='''A read only property that returns the fullpath as a python string.''') + fullpath = property(str, None, doc='''A read only property that returns the fullpath as a python string.''') basename = property(GetFilename, None, doc='''A read only property that returns the path basename as a python string.''') dirname = property(GetDirectory, None, doc='''A read only property that returns the path directory name as a python string.''') exists = property(Exists, None, doc='''A read only property that returns a boolean value that indicates if the file exists.''') diff --git a/gnu/llvm/lldb/bindings/interface/SBInstruction.i b/gnu/llvm/lldb/bindings/interface/SBInstruction.i index e9e018b7dee..a467a6f0d93 100644 --- a/gnu/llvm/lldb/bindings/interface/SBInstruction.i +++ b/gnu/llvm/lldb/bindings/interface/SBInstruction.i @@ -44,6 +44,9 @@ public: const char * GetComment (lldb::SBTarget target); + lldb::InstructionControlFlowKind + GetControlFlowKind(lldb::SBTarget target); + lldb::SBData GetData (lldb::SBTarget target); diff --git a/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfo.i b/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfo.i index 3460dc0d06e..0316c5a5be1 100644 --- a/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfo.i +++ b/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfo.i @@ -20,6 +20,9 @@ public: SBMemoryRegionInfo (const lldb::SBMemoryRegionInfo &rhs); + SBMemoryRegionInfo::SBMemoryRegionInfo(const char *name, lldb::addr_t begin, + lldb::addr_t end, uint32_t permissions, bool mapped, bool stack_memory); + ~SBMemoryRegionInfo (); void diff --git a/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfoList.i b/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfoList.i index c2e74f1cd0d..00975127754 100644 --- a/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfoList.i +++ b/gnu/llvm/lldb/bindings/interface/SBMemoryRegionInfoList.i @@ -24,6 +24,9 @@ public: uint32_t GetSize () const; + bool + GetMemoryRegionContainingAddress (lldb::addr_t addr, SBMemoryRegionInfo ®ion_info); + bool GetMemoryRegionAtIndex (uint32_t idx, SBMemoryRegionInfo ®ion_info); diff --git a/gnu/llvm/lldb/bindings/interface/SBModule.i b/gnu/llvm/lldb/bindings/interface/SBModule.i index 606c9a5bbd0..de476f70626 100644 --- a/gnu/llvm/lldb/bindings/interface/SBModule.i +++ b/gnu/llvm/lldb/bindings/interface/SBModule.i @@ -137,6 +137,16 @@ public: void Clear(); + %feature("docstring", " + Check if the module is file backed. + + @return + + True, if the module is backed by an object file on disk. + False, if the module is backed by an object file in memory.") IsFileBacked; + bool + IsFileBacked() const; + %feature("docstring", " Get const accessor for the module file specification. diff --git a/gnu/llvm/lldb/bindings/interface/SBPlatform.i b/gnu/llvm/lldb/bindings/interface/SBPlatform.i index 65615be7a36..6413784e69e 100644 --- a/gnu/llvm/lldb/bindings/interface/SBPlatform.i +++ b/gnu/llvm/lldb/bindings/interface/SBPlatform.i @@ -177,6 +177,9 @@ public: uint32_t GetOSUpdateVersion (); + void + SetSDKRoot(const char *sysroot); + lldb::SBError Get (lldb::SBFileSpec &src, lldb::SBFileSpec &dst); diff --git a/gnu/llvm/lldb/bindings/interface/SBProcess.i b/gnu/llvm/lldb/bindings/interface/SBProcess.i index 14566a2942d..52f9fc7fa20 100644 --- a/gnu/llvm/lldb/bindings/interface/SBProcess.i +++ b/gnu/llvm/lldb/bindings/interface/SBProcess.i @@ -397,6 +397,9 @@ public: bool IsInstrumentationRuntimePresent(lldb::InstrumentationRuntimeType type); + lldb::SBError + SaveCore(const char *file_name, const char *flavor, lldb::SaveCoreStyle core_style); + lldb::SBError SaveCore(const char *file_name); @@ -419,7 +422,7 @@ public: %feature("autodoc", " Allocates a block of memory within the process, with size and - access permissions specified in the arguments. The permisssions + access permissions specified in the arguments. The permissions argument is an or-combination of zero or more of lldb.ePermissionsWritable, lldb.ePermissionsReadable, and lldb.ePermissionsExecutable. Returns the address diff --git a/gnu/llvm/lldb/bindings/interface/SBSection.i b/gnu/llvm/lldb/bindings/interface/SBSection.i index b86d4e99c5e..a138d81825b 100644 --- a/gnu/llvm/lldb/bindings/interface/SBSection.i +++ b/gnu/llvm/lldb/bindings/interface/SBSection.i @@ -105,6 +105,9 @@ public: uint32_t GetTargetByteSize (); + uint32_t + GetAlignment (); + bool GetDescription (lldb::SBStream &description); @@ -138,6 +141,7 @@ public: data = property(GetSectionData, None, doc='''A read only property that returns an lldb object that represents the bytes for this section (lldb.SBData) for this section.''') type = property(GetSectionType, None, doc='''A read only property that returns an lldb enumeration value (see enumerations that start with "lldb.eSectionType") that represents the type of this section (code, data, etc.).''') target_byte_size = property(GetTargetByteSize, None, doc='''A read only property that returns the size of a target byte represented by this section as a number of host bytes.''') + alignment = property(GetAlignment, None, doc='''A read only property that returns the alignment of this section as a number of host bytes.''') %} #endif diff --git a/gnu/llvm/lldb/bindings/interface/SBSymbol.i b/gnu/llvm/lldb/bindings/interface/SBSymbol.i index fa0b3e4e137..f5efee75e24 100644 --- a/gnu/llvm/lldb/bindings/interface/SBSymbol.i +++ b/gnu/llvm/lldb/bindings/interface/SBSymbol.i @@ -49,6 +49,10 @@ public: SBAddress GetEndAddress (); + uint64_t GetValue(); + + uint64_t GetSize(); + uint32_t GetPrologueByteSize (); diff --git a/gnu/llvm/lldb/bindings/interface/SBSymbolContextList.i b/gnu/llvm/lldb/bindings/interface/SBSymbolContextList.i index e9d4aa8d62d..14566b3e372 100644 --- a/gnu/llvm/lldb/bindings/interface/SBSymbolContextList.i +++ b/gnu/llvm/lldb/bindings/interface/SBSymbolContextList.i @@ -14,7 +14,7 @@ namespace lldb { For example (from test/python_api/target/TestTargetAPI.py), :: def find_functions(self, exe_name): - '''Exercise SBTaget.FindFunctions() API.''' + '''Exercise SBTarget.FindFunctions() API.''' exe = os.path.join(os.getcwd(), exe_name) # Create a target by the debugger. diff --git a/gnu/llvm/lldb/bindings/interface/SBTarget.i b/gnu/llvm/lldb/bindings/interface/SBTarget.i index 3f9e4cdc6d6..e887762b831 100644 --- a/gnu/llvm/lldb/bindings/interface/SBTarget.i +++ b/gnu/llvm/lldb/bindings/interface/SBTarget.i @@ -394,6 +394,9 @@ public: const char * GetTriple (); + const char * + GetABIName(); + %feature("docstring", " Architecture data byte width accessor @@ -412,6 +415,9 @@ public: uint32_t GetCodeByteSize (); + uint32_t + GetMaximumNumberOfChildrenToDisplay() const; + lldb::SBError SetSectionLoadAddress (lldb::SBSection section, lldb::addr_t section_base_addr); @@ -941,7 +947,7 @@ public: %feature("docstring", " Returns true if the module has been loaded in this `SBTarget`. A module can be loaded either by the dynamic loader or by being manually - added to the target (see `SBTarget.AddModule` and the `target module add` command). + added to the target (see `SBTarget.AddModule` and the ``target module add`` command). :rtype: bool ") IsLoaded; diff --git a/gnu/llvm/lldb/bindings/interface/SBThread.i b/gnu/llvm/lldb/bindings/interface/SBThread.i index d847d38f0d6..1e46bd6e21f 100644 --- a/gnu/llvm/lldb/bindings/interface/SBThread.i +++ b/gnu/llvm/lldb/bindings/interface/SBThread.i @@ -405,6 +405,12 @@ public: bool SafeToCallFunctions (); + %feature("autodoc"," + Retruns a SBValue object representing the siginfo for the current signal. + ") GetSiginfo; + lldb::SBValue + GetSiginfo(); + STRING_EXTENSION(SBThread) #ifdef SWIGPYTHON diff --git a/gnu/llvm/lldb/bindings/interface/SBTrace.i b/gnu/llvm/lldb/bindings/interface/SBTrace.i index 0f5bf0ecc8d..e947572c0f8 100644 --- a/gnu/llvm/lldb/bindings/interface/SBTrace.i +++ b/gnu/llvm/lldb/bindings/interface/SBTrace.i @@ -15,8 +15,12 @@ class LLDB_API SBTrace { public: SBTrace(); + SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread); + const char *GetStartConfigurationHelp(); + SBFileSpec SaveToDisk(SBError &error, const SBFileSpec &bundle_dir, bool compact = false); + SBError Start(const SBStructuredData &configuration); SBError Start(const SBThread &thread, const SBStructuredData &configuration); diff --git a/gnu/llvm/lldb/bindings/interface/SBTraceCursor.i b/gnu/llvm/lldb/bindings/interface/SBTraceCursor.i new file mode 100644 index 00000000000..c1c73de3110 --- /dev/null +++ b/gnu/llvm/lldb/bindings/interface/SBTraceCursor.i @@ -0,0 +1,58 @@ +//===-- SWIG Interface for SBTraceCursor.h ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +%feature("docstring", +"Represents a trace cursor." +) SBTrace; +class LLDB_API SBTraceCursor { +public: + SBTraceCursor(); + + SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp); + + void SetForwards(bool forwards); + + bool IsForwards() const; + + void Next(); + + bool HasValue(); + + bool GoToId(lldb::user_id_t id); + + bool HasId(lldb::user_id_t id) const; + + lldb::user_id_t GetId() const; + + bool Seek(int64_t offset, lldb::TraceCursorSeekType origin); + + lldb::TraceItemKind GetItemKind() const; + + bool IsError() const; + + const char *GetError() const; + + bool IsEvent() const; + + lldb::TraceEvent GetEventType() const; + + const char *GetEventTypeAsString() const; + + bool IsInstruction() const; + + lldb::addr_t GetLoadAddress() const; + + lldb::cpu_id_t GetCPU() const; + + bool IsValid() const; + + explicit operator bool() const; +}; +} // namespace lldb diff --git a/gnu/llvm/lldb/bindings/interface/SBType.i b/gnu/llvm/lldb/bindings/interface/SBType.i index 500bc99ca8c..5bead82cd2c 100644 --- a/gnu/llvm/lldb/bindings/interface/SBType.i +++ b/gnu/llvm/lldb/bindings/interface/SBType.i @@ -229,7 +229,7 @@ public: function returns ``0``. * C++: Same as in C. * Objective-C: Same as in C. For Objective-C classes this always returns - `0`` as the actual size depends on runtime information. + ``0`` as the actual size depends on runtime information. ") GetByteSize; uint64_t GetByteSize(); @@ -354,6 +354,18 @@ public: bool IsScopedEnumerationType (); + %feature("docstring", + "Returns true if this type is an aggregate type. + + Language-specific behaviour: + + * C: Returns true for struct values, arrays, and vectors. + * C++: Same a C. Also includes class instances. + * Objective-C: Same as C. Also includes class instances. + ") IsAggregateType; + bool + IsAggregateType (); + %feature("docstring", "Returns a type that represents a pointer to this type. @@ -494,7 +506,7 @@ public: Language-specific behaviour: - * C: Returns a constant-size array `T[size]` for any non-void type. + * C: Returns a constant-size array ``T[size]`` for any non-void type. * C++: Same as in C. * Objective-C: Same as in C. @@ -525,8 +537,8 @@ public: "Returns the `BasicType` value that is most appropriate to this type. Returns `eBasicTypeInvalid` if no appropriate `BasicType` was found or this - type is invalid. See the `BasicType` documentation for the language-specific m - aning of each `BasicType` value. + type is invalid. See the `BasicType` documentation for the language-specific + meaning of each `BasicType` value. **Overload behaviour:** When called with a `BasicType` parameter, the following behaviour applies: @@ -719,8 +731,8 @@ public: * C: Always returns ``0``. * C++: If this type is a class template instantiation then this returns the - number of template parameters that were used in this instantiation. This i - cludes both explicit and implicit template parameters. + number of template parameters that were used in this instantiation. This + includes both explicit and implicit template parameters. * Objective-C: Always returns ``0``. ") GetNumberOfTemplateArguments; uint32_t @@ -837,6 +849,21 @@ public: lldb::SBTypeMemberFunction GetMemberFunctionAtIndex (uint32_t idx); + %feature("docstring", + "Returns true if the type is completely defined. + + Language-specific behaviour: + + * C: Returns false for struct types that were only forward declared in the + type's `SBTarget`/`SBModule`. Otherwise returns true. + * C++: Returns false for template/non-template struct/class types and + scoped enums that were only forward declared inside the type's + `SBTarget`/`SBModule`. Otherwise returns true. + * Objective-C: Follows the same behavior as C for struct types. Objective-C + classes are considered complete unless they were only forward declared via + ``@class ClassName`` in the type's `SBTarget`/`SBModule`. Otherwise + returns true. + ") IsTypeComplete; bool IsTypeComplete (); diff --git a/gnu/llvm/lldb/bindings/interface/SBTypeNameSpecifier.i b/gnu/llvm/lldb/bindings/interface/SBTypeNameSpecifier.i index 772f7c17409..4bd5f205cfb 100644 --- a/gnu/llvm/lldb/bindings/interface/SBTypeNameSpecifier.i +++ b/gnu/llvm/lldb/bindings/interface/SBTypeNameSpecifier.i @@ -20,6 +20,9 @@ namespace lldb { SBTypeNameSpecifier (const char* name, bool is_regex = false); + SBTypeNameSpecifier (const char* name, + lldb::FormatterMatchType match_type); + SBTypeNameSpecifier (SBType type); SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs); @@ -40,6 +43,9 @@ namespace lldb { lldb::SBType GetType (); + lldb::FormatterMatchType + GetMatchType(); + bool IsRegex(); diff --git a/gnu/llvm/lldb/bindings/interface/SBValue.i b/gnu/llvm/lldb/bindings/interface/SBValue.i index dd012e667a2..bc66a4ae28f 100644 --- a/gnu/llvm/lldb/bindings/interface/SBValue.i +++ b/gnu/llvm/lldb/bindings/interface/SBValue.i @@ -410,6 +410,9 @@ public: bool SetData (lldb::SBData &data, lldb::SBError& error); + lldb::SBValue + Clone(const char *new_name); + lldb::addr_t GetLoadAddress(); diff --git a/gnu/llvm/lldb/bindings/interface/SBValueList.i b/gnu/llvm/lldb/bindings/interface/SBValueList.i index 76fa937b987..e03b5c649db 100644 --- a/gnu/llvm/lldb/bindings/interface/SBValueList.i +++ b/gnu/llvm/lldb/bindings/interface/SBValueList.i @@ -102,8 +102,12 @@ public: lldb::SBValue GetFirstValueByName (const char* name) const; + lldb::SBError GetError(); + %extend { +#ifdef SWIGPYTHON %nothreadallow; +#endif std::string lldb::SBValueList::__str__ (){ lldb::SBStream description; const size_t n = $self->GetSize(); @@ -122,7 +126,9 @@ public: --desc_len; return std::string(desc, desc_len); } +#ifdef SWIGPYTHON %clearnothreadallow; +#endif } #ifdef SWIGPYTHON diff --git a/gnu/llvm/lldb/bindings/interfaces.swig b/gnu/llvm/lldb/bindings/interfaces.swig index c9a6d0f0605..d984711bbd8 100644 --- a/gnu/llvm/lldb/bindings/interfaces.swig +++ b/gnu/llvm/lldb/bindings/interfaces.swig @@ -1,8 +1,5 @@ /* Various liblldb typedefs that SWIG needs to know about. */ #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ -/* The ISO C99 standard specifies that in C++ implementations limit macros such - as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */ -#define __STDC_LIMIT_MACROS %include "stdint.i" %include "lldb/lldb-defines.h" @@ -69,6 +66,7 @@ %include "./interface/SBThreadCollection.i" %include "./interface/SBThreadPlan.i" %include "./interface/SBTrace.i" +%include "./interface/SBTraceCursor.i" %include "./interface/SBType.i" %include "./interface/SBTypeCategory.i" %include "./interface/SBTypeEnumMember.i" diff --git a/gnu/llvm/lldb/bindings/lua/CMakeLists.txt b/gnu/llvm/lldb/bindings/lua/CMakeLists.txt index 7148f137045..1a739a9805e 100644 --- a/gnu/llvm/lldb/bindings/lua/CMakeLists.txt +++ b/gnu/llvm/lldb/bindings/lua/CMakeLists.txt @@ -17,3 +17,55 @@ add_custom_command( add_custom_target(swig_wrapper_lua ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapLua.cpp ) + +function(create_lua_package swig_target working_dir pkg_dir) + cmake_parse_arguments(ARG "NOINIT" "" "FILES" ${ARGN}) + add_custom_command(TARGET ${swig_target} POST_BUILD VERBATIM + COMMAND ${CMAKE_COMMAND} -E make_directory ${pkg_dir} + WORKING_DIRECTORY ${working_dir}) +endfunction() + +function(finish_swig_lua swig_target lldb_lua_bindings_dir lldb_lua_target_dir) + add_custom_target(${swig_target} ALL VERBATIM + COMMAND ${CMAKE_COMMAND} -E make_directory ${lldb_lua_target_dir} + DEPENDS swig_wrapper_lua + COMMENT "LLDB Lua API") + if(LLDB_BUILD_FRAMEWORK) + set(LIBLLDB_SYMLINK_DEST "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/LLDB") + else() + set(LIBLLDB_SYMLINK_DEST "${LLVM_SHLIB_OUTPUT_INTDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + if(WIN32) + if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb_d.pyd") + else() + set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb.pyd") + endif() + else() + set(LIBLLDB_SYMLINK_OUTPUT_FILE "lldb.so") + endif() + create_relative_symlink(${swig_target} ${LIBLLDB_SYMLINK_DEST} + ${lldb_lua_target_dir} ${LIBLLDB_SYMLINK_OUTPUT_FILE}) + set(lldb_lua_library_target "${swig_target}-library") + add_custom_target(${lldb_lua_library_target}) + add_dependencies(${lldb_lua_library_target} ${swig_target}) + + # Ensure we do the Lua post-build step when building lldb. + add_dependencies(lldb ${swig_target}) + + if(LLDB_BUILD_FRAMEWORK) + set(LLDB_LUA_INSTALL_PATH ${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Resources/Python) + else() + set(LLDB_LUA_INSTALL_PATH ${LLDB_LUA_RELATIVE_PATH}) + endif() + install(DIRECTORY ${lldb_lua_target_dir}/ + DESTINATION ${LLDB_LUA_INSTALL_PATH} + COMPONENT ${lldb_lua_library_target}) + + set(lldb_lua_library_install_target "install-${lldb_lua_library_target}") + if (NOT LLVM_ENABLE_IDE) + add_llvm_install_targets(${lldb_lua_library_install_target} + COMPONENT ${lldb_lua_library_target} + DEPENDS ${lldb_lua_library_target}) + endif() +endfunction() diff --git a/gnu/llvm/lldb/bindings/lua/lua-swigsafecast.swig b/gnu/llvm/lldb/bindings/lua/lua-swigsafecast.swig index 0b67c41434e..35cb5e22a4c 100644 --- a/gnu/llvm/lldb/bindings/lua/lua-swigsafecast.swig +++ b/gnu/llvm/lldb/bindings/lua/lua-swigsafecast.swig @@ -1,27 +1,20 @@ -template -void -PushSBClass (lua_State* L, SBClass* obj); +template void PushSBClass(lua_State *L, SBClass *obj); -void -PushSBClass (lua_State* L, lldb::SBFrame* frame_sb) -{ - SWIG_NewPointerObj(L, frame_sb, SWIGTYPE_p_lldb__SBFrame, 0); +void PushSBClass(lua_State *L, lldb::SBFrame *frame_sb) { + SWIG_NewPointerObj(L, frame_sb, SWIGTYPE_p_lldb__SBFrame, 0); } -void -PushSBClass (lua_State* L, lldb::SBBreakpointLocation* breakpoint_location_sb) -{ - SWIG_NewPointerObj(L, breakpoint_location_sb, SWIGTYPE_p_lldb__SBBreakpointLocation, 0); +void PushSBClass(lua_State *L, + lldb::SBBreakpointLocation *breakpoint_location_sb) { + SWIG_NewPointerObj(L, breakpoint_location_sb, + SWIGTYPE_p_lldb__SBBreakpointLocation, 0); } -void -PushSBClass (lua_State* L, lldb::SBWatchpoint* watchpoint_sb) -{ - SWIG_NewPointerObj(L, watchpoint_sb, SWIGTYPE_p_lldb__SBWatchpoint, 0); +void PushSBClass(lua_State *L, lldb::SBWatchpoint *watchpoint_sb) { + SWIG_NewPointerObj(L, watchpoint_sb, SWIGTYPE_p_lldb__SBWatchpoint, 0); } -void -PushSBClass (lua_State* L, lldb::SBStructuredData* structured_data_sb) -{ - SWIG_NewPointerObj(L, structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0); +void PushSBClass(lua_State *L, lldb::SBStructuredData *structured_data_sb) { + SWIG_NewPointerObj(L, structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, + 0); } diff --git a/gnu/llvm/lldb/bindings/lua/lua-typemaps.swig b/gnu/llvm/lldb/bindings/lua/lua-typemaps.swig index d912137a567..56756936a53 100644 --- a/gnu/llvm/lldb/bindings/lua/lua-typemaps.swig +++ b/gnu/llvm/lldb/bindings/lua/lua-typemaps.swig @@ -12,7 +12,7 @@ // Primitive integer mapping %typemap(in,checkfn="lua_isinteger") TYPE -%{ $1 = (TYPE)lua_tointeger(L, $input); %} +%{ $1 = ($type)lua_tointeger(L, $input); %} %typemap(in,checkfn="lua_isinteger") const TYPE&($basetype temp) %{ temp=($basetype)lua_tointeger(L,$input); $1=&temp;%} %typemap(out) TYPE @@ -54,6 +54,7 @@ LLDB_NUMBER_TYPEMAP(signed long); LLDB_NUMBER_TYPEMAP(long long); LLDB_NUMBER_TYPEMAP(unsigned long long); LLDB_NUMBER_TYPEMAP(signed long long); +LLDB_NUMBER_TYPEMAP(enum SWIGTYPE); %apply unsigned long { size_t }; %apply const unsigned long & { const size_t & }; @@ -75,31 +76,240 @@ LLDB_NUMBER_TYPEMAP(signed long long); // typemap for a char buffer %typemap(in) (char *dst, size_t dst_len) { - $2 = luaL_checkinteger(L, $input); - if ($2 <= 0) { - return luaL_error(L, "Positive integer expected"); - } - $1 = (char *) malloc($2); + $2 = luaL_checkinteger(L, $input); + if ($2 <= 0) { + return luaL_error(L, "Positive integer expected"); + } + $1 = (char *)malloc($2); } // SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated // as char data instead of byte data. %typemap(in) (void *char_buf, size_t size) = (char *dst, size_t dst_len); +// Also SBProcess::ReadMemory. +%typemap(in) (void *buf, size_t size) = (char *dst, size_t dst_len); + // Return the char buffer. Discarding any previous return result %typemap(argout) (char *dst, size_t dst_len) { - lua_pop(L, 1); // Blow away the previous result - if ($result == 0) { - lua_pushliteral(L, ""); - } else { - lua_pushlstring(L, (const char *)$1, $result); - } - free($1); - // SWIG_arg was already incremented + lua_pop(L, 1); // Blow away the previous result + if ($result == 0) { + lua_pushliteral(L, ""); + } else { + lua_pushlstring(L, (const char *)$1, $result); + } + free($1); + // SWIG_arg was already incremented } // SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated // as char data instead of byte data. %typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len); +// Also SBProcess::ReadMemory. +%typemap(argout) (void *buf, size_t size) = (char *dst, size_t dst_len); + +//===----------------------------------------------------------------------===// + +// Typemap for handling a snprintf-like API like SBThread::GetStopDescription. + +%typemap(in) (char *dst_or_null, size_t dst_len) { + $2 = luaL_checkinteger(L, $input); + if ($2 <= 0) { + return luaL_error(L, "Positive integer expected"); + } + $1 = (char *)malloc($2); +} + +%typemap(argout) (char *dst_or_null, size_t dst_len) { + lua_pop(L, 1); // Blow away the previous result + lua_pushlstring(L, (const char *)$1, $result); + free($1); + // SWIG_arg was already incremented +} + +//===----------------------------------------------------------------------===// + +// Typemap for handling SBModule::GetVersion + +%typemap(in) (uint32_t *versions, uint32_t num_versions) { + $2 = 99; + $1 = (uint32_t *)malloc(sizeof(uint32_t) * $2); +} + +%typemap(argout) (uint32_t *versions, uint32_t num_versions) { + uint32_t count = result; + if (count >= $2) + count = $2; + lua_newtable(L); + int i = 0; + while (i++ < count) { + lua_pushinteger(L, $1[i - 1]); + lua_seti(L, -2, i); + } + SWIG_arg++; + free($1); +} + +//===----------------------------------------------------------------------===// + +// Typemap for handling SBDebugger::SetLoggingCallback + +%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) { + $1 = LLDBSwigLuaCallLuaLogOutputCallback; + $2 = (void *)L; + + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_settop(L, 2); + + lua_pushlightuserdata(L, (void *)&LLDBSwigLuaCallLuaLogOutputCallback); + lua_insert(L, 2); + lua_settable(L, LUA_REGISTRYINDEX); +} + +//===----------------------------------------------------------------------===// + +// Typemap for handling SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len) + +%typemap(in) (const char *cstr, uint32_t cstr_len) { + $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2); +} + +// Typemap for handling SBProcess::PutSTDIN + +%typemap(in) (const char *src, size_t src_len) { + $1 = (char *)luaL_checklstring(L, $input, &$2); +} + +// Typemap for handling SBProcess::WriteMemory, SBTarget::GetInstructions... + +%typemap(in) (const void *buf, size_t size), + (const void *data, size_t data_len) { + $1 = (void *)luaL_checklstring(L, $input, &$2); +} + +//===----------------------------------------------------------------------===// + +// Typemap for handling char ** in SBTarget::LaunchSimple, SBTarget::Launch... + +// It should accept a Lua table of strings, for stuff like "argv" and "envp". + +%typemap(in) char ** { + if (lua_istable(L, $input)) { + size_t size = lua_rawlen(L, $input); + $1 = (char **)malloc((size + 1) * sizeof(char *)); + int i = 0, j = 0; + while (i++ < size) { + lua_rawgeti(L, $input, i); + if (!lua_isstring(L, -1)) { + // if current element cannot be converted to string, raise an error + lua_pop(L, 1); + return luaL_error(L, "List should only contain strings"); + } + $1[j++] = (char *)lua_tostring(L, -1); + lua_pop(L, 1); + } + $1[j] = 0; + } else if (lua_isnil(L, $input)) { + // "nil" is also acceptable, equivalent as an empty table + $1 = NULL; + } else { + return luaL_error(L, "A list of strings expected"); + } +} + +%typemap(freearg) char ** { + free((char *) $1); +} + +%typecheck(SWIG_TYPECHECK_STRING_ARRAY) char ** { + $1 = (lua_istable(L, $input) || lua_isnil(L, $input)); +} + +//===----------------------------------------------------------------------===// + +// Typemap for file handles (e.g. used in SBDebugger::SetOutputFile) + +%typemap(in) lldb::FileSP { + luaL_Stream *p = (luaL_Stream *)luaL_checkudata(L, $input, LUA_FILEHANDLE); + lldb::FileSP file_sp; + file_sp = std::make_shared(p->f, false); + if (!file_sp->IsValid()) + return luaL_error(L, "Invalid file"); + $1 = file_sp; +} + +%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP { + $1 = (lua_isuserdata(L, $input)) && + (luaL_testudata(L, $input, LUA_FILEHANDLE) != nullptr); +} + +// Typemap for file handles (e.g. used in SBDebugger::GetOutputFileHandle) + +%typemap(out) lldb::FileSP { + lldb::FileSP sp = $1; + if (sp && sp->IsValid()) { + luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream)); + p->closef = &LLDBSwigLuaCloseFileHandle; + p->f = sp->GetStream(); + luaL_setmetatable(L, LUA_FILEHANDLE); + SWIG_arg++; + } +} + +//===----------------------------------------------------------------------===// + +// Typemap for SBData::CreateDataFromUInt64Array, SBData::SetDataFromUInt64Array ... + +%typemap(in) (uint64_t* array, size_t array_len), + (uint32_t* array, size_t array_len), + (int64_t* array, size_t array_len), + (int32_t* array, size_t array_len), + (double* array, size_t array_len) { + if (lua_istable(L, $input)) { + // It should accept a table of numbers. + $2 = lua_rawlen(L, $input); + $1 = ($1_ltype)malloc(($2) * sizeof($*1_type)); + int i = 0, j = 0; + while (i++ < $2) { + lua_rawgeti(L, $input, i); + if (!lua_isnumber(L, -1)) { + // if current element cannot be converted to number, raise an error + lua_pop(L, 1); + return luaL_error(L, "List should only contain numbers"); + } + $1[j++] = ($*1_ltype) lua_tonumber(L, -1); + lua_pop(L, 1); + } + } else if (lua_isnil(L, $input)) { + // "nil" is also acceptable, equivalent as an empty table + $1 = NULL; + $2 = 0; + } else { + // else raise an error + return luaL_error(L, "A list of numbers expected."); + } +} + +%typemap(freearg) (uint64_t* array, size_t array_len), + (uint32_t* array, size_t array_len), + (int64_t* array, size_t array_len), + (int32_t* array, size_t array_len), + (double* array, size_t array_len) { + free($1); +} + +//===----------------------------------------------------------------------===// + +// Typemap for SBCommandReturnObject::PutCString + +%typemap(in) (const char *string, int len) { + if (lua_isnil(L, $input)) { + $1 = NULL; + $2 = 0; + } else { + $1 = (char *)luaL_checklstring(L, $input, (size_t *)&$2); + } +} + //===----------------------------------------------------------------------===// diff --git a/gnu/llvm/lldb/bindings/lua/lua-wrapper.swig b/gnu/llvm/lldb/bindings/lua/lua-wrapper.swig index e070bae2368..a36e69a6fc9 100644 --- a/gnu/llvm/lldb/bindings/lua/lua-wrapper.swig +++ b/gnu/llvm/lldb/bindings/lua/lua-wrapper.swig @@ -1,92 +1,87 @@ %header %{ -template -void -PushSBClass(lua_State* L, T* obj); - -%} - -%wrapper %{ +template void PushSBClass(lua_State * L, T * obj); // This function is called from Lua::CallBreakpointCallback -SWIGEXPORT llvm::Expected -LLDBSwigLuaBreakpointCallbackFunction -( - lua_State *L, - lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp, - StructuredDataImpl *extra_args_impl -) -{ - lldb::SBFrame sb_frame(stop_frame_sp); - lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); - int nargs = 2; - - llvm::Optional extra_args; - if (extra_args_impl) - extra_args = lldb::SBStructuredData(extra_args_impl); - - // Push the Lua wrappers - PushSBClass(L, &sb_frame); - PushSBClass(L, &sb_bp_loc); - - if (extra_args.hasValue()) { - PushSBClass(L, extra_args.getPointer()); - nargs++; - } - - // Call into the Lua callback passing 'sb_frame' and 'sb_bp_loc'. - // Expects a boolean return. - if (lua_pcall(L, nargs, 1, 0) != LUA_OK) { - llvm::Error E = llvm::make_error( - llvm::formatv("{0}\n", lua_tostring(L, -1)), - llvm::inconvertibleErrorCode()); - // Pop error message from the stack. - lua_pop(L, 1); - return std::move(E); - } - - // Boolean return from the callback - bool stop = lua_toboolean(L, -1); - lua_pop(L, 1); - - return stop; +llvm::Expected lldb_private::LLDBSwigLuaBreakpointCallbackFunction( + lua_State * L, lldb::StackFrameSP stop_frame_sp, + lldb::BreakpointLocationSP bp_loc_sp, + const StructuredDataImpl &extra_args_impl) { + lldb::SBFrame sb_frame(stop_frame_sp); + lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); + int nargs = 2; + + lldb::SBStructuredData extra_args(extra_args_impl); + + // Push the Lua wrappers + PushSBClass(L, &sb_frame); + PushSBClass(L, &sb_bp_loc); + + if (extra_args.IsValid()) { + PushSBClass(L, &extra_args); + nargs++; + } + + // Call into the Lua callback passing 'sb_frame' and 'sb_bp_loc'. + // Expects a boolean return. + if (lua_pcall(L, nargs, 1, 0) != LUA_OK) { + llvm::Error E = llvm::make_error( + llvm::formatv("{0}\n", lua_tostring(L, -1)), + llvm::inconvertibleErrorCode()); + // Pop error message from the stack. + lua_pop(L, 1); + return std::move(E); + } + + // Boolean return from the callback + bool stop = lua_toboolean(L, -1); + lua_pop(L, 1); + + return stop; } // This function is called from Lua::CallWatchpointCallback -SWIGEXPORT llvm::Expected -LLDBSwigLuaWatchpointCallbackFunction -( - lua_State *L, - lldb::StackFrameSP stop_frame_sp, - lldb::WatchpointSP wp_sp -) -{ - lldb::SBFrame sb_frame(stop_frame_sp); - lldb::SBWatchpoint sb_wp(wp_sp); - int nargs = 2; - - // Push the Lua wrappers - PushSBClass(L, &sb_frame); - PushSBClass(L, &sb_wp); - - // Call into the Lua callback passing 'sb_frame' and 'sb_wp'. - // Expects a boolean return. - if (lua_pcall(L, nargs, 1, 0) != LUA_OK) { - llvm::Error E = llvm::make_error( - llvm::formatv("{0}\n", lua_tostring(L, -1)), - llvm::inconvertibleErrorCode()); - // Pop error message from the stack. - lua_pop(L, 1); - return std::move(E); - } - - // Boolean return from the callback - bool stop = lua_toboolean(L, -1); - lua_pop(L, 1); - - return stop; +llvm::Expected lldb_private::LLDBSwigLuaWatchpointCallbackFunction( + lua_State * L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp) { + lldb::SBFrame sb_frame(stop_frame_sp); + lldb::SBWatchpoint sb_wp(wp_sp); + int nargs = 2; + + // Push the Lua wrappers + PushSBClass(L, &sb_frame); + PushSBClass(L, &sb_wp); + + // Call into the Lua callback passing 'sb_frame' and 'sb_wp'. + // Expects a boolean return. + if (lua_pcall(L, nargs, 1, 0) != LUA_OK) { + llvm::Error E = llvm::make_error( + llvm::formatv("{0}\n", lua_tostring(L, -1)), + llvm::inconvertibleErrorCode()); + // Pop error message from the stack. + lua_pop(L, 1); + return std::move(E); + } + + // Boolean return from the callback + bool stop = lua_toboolean(L, -1); + lua_pop(L, 1); + + return stop; +} + +static void LLDBSwigLuaCallLuaLogOutputCallback(const char *str, void *baton) { + lua_State *L = (lua_State *)baton; + + lua_pushlightuserdata(L, (void *)&LLDBSwigLuaCallLuaLogOutputCallback); + lua_gettable(L, LUA_REGISTRYINDEX); + + // FIXME: There's no way to report errors back to the user + lua_pushstring(L, str); + lua_pcall(L, 1, 0, 0); } +static int LLDBSwigLuaCloseFileHandle(lua_State * L) { + return luaL_error(L, "You cannot close a file handle used by lldb."); +} %} diff --git a/gnu/llvm/lldb/bindings/lua/lua.swig b/gnu/llvm/lldb/bindings/lua/lua.swig index c702e496408..92f85fee22f 100644 --- a/gnu/llvm/lldb/bindings/lua/lua.swig +++ b/gnu/llvm/lldb/bindings/lua/lua.swig @@ -17,6 +17,11 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" #include "../bindings/lua/lua-swigsafecast.swig" +#include "../source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h" + +// required headers for typemaps +#include "lldb/Host/File.h" + using namespace lldb_private; using namespace lldb; %} diff --git a/gnu/llvm/lldb/bindings/macros.swig b/gnu/llvm/lldb/bindings/macros.swig index 6793a11c5bd..84f24424573 100644 --- a/gnu/llvm/lldb/bindings/macros.swig +++ b/gnu/llvm/lldb/bindings/macros.swig @@ -1,6 +1,6 @@ %define STRING_EXTENSION_LEVEL(Class, Level) %extend { - std::string lldb:: ## Class ## ::__str__(){ + std::string lldb:: ## Class ## ::__repr__(){ lldb::SBStream stream; $self->GetDescription (stream, Level); const char *desc = stream.GetData(); @@ -15,7 +15,7 @@ %define STRING_EXTENSION(Class) %extend { - std::string lldb:: ## Class ## ::__str__(){ + std::string lldb:: ## Class ## ::__repr__(){ lldb::SBStream stream; $self->GetDescription (stream); const char *desc = stream.GetData(); diff --git a/gnu/llvm/lldb/bindings/python/CMakeLists.txt b/gnu/llvm/lldb/bindings/python/CMakeLists.txt index 9422ee00cb5..c631faf52ac 100644 --- a/gnu/llvm/lldb/bindings/python/CMakeLists.txt +++ b/gnu/llvm/lldb/bindings/python/CMakeLists.txt @@ -23,6 +23,18 @@ add_custom_target(swig_wrapper_python ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lldb.py ) +if (NOT WIN32) +add_custom_command( + OUTPUT ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python + VERBATIM + COMMAND ${CMAKE_COMMAND} -E copy lldb-python ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) +add_custom_target(lldb-python-wrapper ALL DEPENDS + ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-python +) +endif() + function(create_python_package swig_target working_dir pkg_dir) cmake_parse_arguments(ARG "NOINIT" "" "FILES" ${ARGN}) if(ARG_FILES) @@ -40,20 +52,6 @@ function(create_python_package swig_target working_dir pkg_dir) WORKING_DIRECTORY ${working_dir}) endfunction() -function(create_relative_symlink swig_target dest_file output_dir output_name) - get_filename_component(dest_file ${dest_file} ABSOLUTE) - get_filename_component(output_dir ${output_dir} ABSOLUTE) - file(RELATIVE_PATH rel_dest_file ${output_dir} ${dest_file}) - if(CMAKE_HOST_UNIX) - set(LLVM_LINK_OR_COPY create_symlink) - else() - set(LLVM_LINK_OR_COPY copy) - endif() - add_custom_command(TARGET ${swig_target} POST_BUILD VERBATIM - COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} ${rel_dest_file} ${output_name} - WORKING_DIRECTORY ${output_dir}) -endfunction() - function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_target_dir) # Add a Post-Build Event to copy over Python files and create the symlink to # liblldb.so for the Python API(hardlink on Windows). @@ -62,13 +60,6 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar DEPENDS ${lldb_python_bindings_dir}/lldb.py COMMENT "Python script sym-linking LLDB Python API") - if(NOT LLDB_USE_SYSTEM_SIX) - add_custom_command(TARGET ${swig_target} POST_BUILD VERBATIM - COMMAND ${CMAKE_COMMAND} -E copy - "${LLDB_SOURCE_DIR}/third_party/Python/module/six/six.py" - "${lldb_python_target_dir}/../six.py") - endif() - add_custom_command(TARGET ${swig_target} POST_BUILD VERBATIM COMMAND ${CMAKE_COMMAND} -E copy "${lldb_python_bindings_dir}/lldb.py" @@ -111,11 +102,19 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar FILES "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_process.py") + create_python_package( + ${swig_target} + ${lldb_python_target_dir} + "plugins" + FILES + "${LLDB_SOURCE_DIR}/examples/python/scripted_process/scripted_platform.py") + if(APPLE) create_python_package( ${swig_target} ${lldb_python_target_dir} "macosx" FILES "${LLDB_SOURCE_DIR}/examples/python/crashlog.py" + "${LLDB_SOURCE_DIR}/examples/python/scripted_process/crashlog_scripted_process.py" "${LLDB_SOURCE_DIR}/examples/darwin/heap_find/heap.py") create_python_package( @@ -137,18 +136,15 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar else() set(LIBLLDB_SYMLINK_DEST "${LLVM_SHLIB_OUTPUT_INTDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}") endif() - if(WIN32) - if(CMAKE_BUILD_TYPE STREQUAL Debug) - set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb_d.pyd") - else() - set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb.pyd") - endif() - else() - set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb.so") - endif() + set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb${LLDB_PYTHON_EXT_SUFFIX}") create_relative_symlink(${swig_target} ${LIBLLDB_SYMLINK_DEST} ${lldb_python_target_dir} ${LIBLLDB_SYMLINK_OUTPUT_FILE}) + + if (NOT WIN32) + add_dependencies(${swig_target} lldb-python-wrapper) + endif() + if(NOT LLDB_BUILD_FRAMEWORK) set(LLDB_ARGDUMPER_FILENAME "lldb-argdumper${CMAKE_EXECUTABLE_SUFFIX}") create_relative_symlink(${swig_target} "${LLVM_RUNTIME_OUTPUT_INTDIR}/${LLDB_ARGDUMPER_FILENAME}" @@ -163,7 +159,7 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar # Install the LLDB python module if(LLDB_BUILD_FRAMEWORK) - set(LLDB_PYTHON_INSTALL_PATH ${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Resources/Python) + set(LLDB_PYTHON_INSTALL_PATH ${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/Resources/Python) else() set(LLDB_PYTHON_INSTALL_PATH ${LLDB_PYTHON_RELATIVE_PATH}) endif() diff --git a/gnu/llvm/lldb/bindings/python/createPythonInit.py b/gnu/llvm/lldb/bindings/python/createPythonInit.py index 3deb9159b70..4ad7320675f 100644 --- a/gnu/llvm/lldb/bindings/python/createPythonInit.py +++ b/gnu/llvm/lldb/bindings/python/createPythonInit.py @@ -10,6 +10,14 @@ importNames = ', '.join('"{}"'.format(getFileName(f)) for f in pkgFiles) script = """__all__ = [{import_names}] for x in __all__: __import__('lldb.{pkg_name}.' + x) + +def __lldb_init_module(debugger, internal_dict): + import lldb + for x in __all__: + submodule = getattr(lldb.{pkg_name}, x) + lldb_init = getattr(submodule, '__lldb_init_module', None) + if lldb_init: + lldb_init(debugger, internal_dict) """.format(import_names=importNames, pkg_name=pkgRelDir.replace("/", ".")) pkgIniFile = os.path.normpath(os.path.join(pkgRelDir, "__init__.py")) diff --git a/gnu/llvm/lldb/bindings/python/get-python-config.py b/gnu/llvm/lldb/bindings/python/get-python-config.py new file mode 100755 index 00000000000..6369e32a491 --- /dev/null +++ b/gnu/llvm/lldb/bindings/python/get-python-config.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +import os +import sys +import argparse +import sysconfig + + +def relpath_nodots(path, base): + rel = os.path.normpath(os.path.relpath(path, base)) + assert not os.path.isabs(rel) + parts = rel.split(os.path.sep) + if parts and parts[0] == '..': + raise ValueError(f"{path} is not under {base}") + return rel + +def main(): + parser = argparse.ArgumentParser(description="extract cmake variables from python") + parser.add_argument("variable_name") + args = parser.parse_args() + if args.variable_name == "LLDB_PYTHON_RELATIVE_PATH": + # LLDB_PYTHON_RELATIVE_PATH is the relative path from lldb's prefix + # to where lldb's python libraries will be installed. + # + # The way we're going to compute this is to take the relative path from + # PYTHON'S prefix to where python libraries are supposed to be + # installed. + # + # The result is if LLDB and python are give the same prefix, then + # lldb's python lib will be put in the correct place for python to find it. + # If not, you'll have to use lldb -P or lldb -print-script-interpreter-info + # to figure out where it is. + try: + print(relpath_nodots(sysconfig.get_path("platlib"), sys.prefix)) + except ValueError: + # Try to fall back to something reasonable if sysconfig's platlib + # is outside of sys.prefix + if os.name == 'posix': + print('lib/python%d.%d/site-packages' % sys.version_info[:2]) + elif os.name == 'nt': + print('Lib\\site-packages') + else: + raise + elif args.variable_name == "LLDB_PYTHON_EXE_RELATIVE_PATH": + tried = list() + exe = sys.executable + prefix = os.path.realpath(sys.prefix) + while True: + try: + print(relpath_nodots(exe, prefix)) + break + except ValueError: + tried.append(exe) + # Retry if the executable is symlinked or similar. + # This is roughly equal to os.path.islink, except it also works for junctions on Windows. + if os.path.realpath(exe) != exe: + exe = os.path.realpath(exe) + continue + else: + print("Could not find a relative path to sys.executable under sys.prefix", file=sys.stderr) + for e in tried: + print("tried:", e, file=sys.stderr) + print("realpath(sys.prefix):", prefix, file=sys.stderr) + print("sys.prefix:", sys.prefix, file=sys.stderr) + sys.exit(1) + elif args.variable_name == "LLDB_PYTHON_EXT_SUFFIX": + print(sysconfig.get_config_var('EXT_SUFFIX')) + else: + parser.error(f"unknown variable {args.variable_name}") + +if __name__ == '__main__': + main() diff --git a/gnu/llvm/lldb/bindings/python/lldb-python b/gnu/llvm/lldb/bindings/python/lldb-python new file mode 100755 index 00000000000..3bb3b332d85 --- /dev/null +++ b/gnu/llvm/lldb/bindings/python/lldb-python @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +import subprocess +import os +import sys +import json + +lldb = os.path.join(os.path.dirname(__file__), 'lldb') + +info_json = subprocess.run([lldb, "-l", "python", "-print-script-interpreter-info"], + check=True, stdout=subprocess.PIPE, encoding='utf8').stdout +info = json.loads(info_json) + +os.environ["PYTHONPATH"] = ( + info["lldb-pythonpath"] + os.path.pathsep + os.environ.get("PYTHONPATH", "")) + +os.execl(info["executable"], info["executable"], *sys.argv[1:]) diff --git a/gnu/llvm/lldb/bindings/python/python-extensions.swig b/gnu/llvm/lldb/bindings/python/python-extensions.swig index b98b0d458f0..cb841af070a 100644 --- a/gnu/llvm/lldb/bindings/python/python-extensions.swig +++ b/gnu/llvm/lldb/bindings/python/python-extensions.swig @@ -565,6 +565,7 @@ def is_numeric_type(basic_type): if basic_type == eBasicTypeUnsignedWChar: return (True,False) if basic_type == eBasicTypeChar16: return (True,False) if basic_type == eBasicTypeChar32: return (True,False) + if basic_type == eBasicTypeChar8: return (True,False) if basic_type == eBasicTypeShort: return (True,True) if basic_type == eBasicTypeUnsignedShort: return (True,False) if basic_type == eBasicTypeInt: return (True,True) diff --git a/gnu/llvm/lldb/bindings/python/python-swigsafecast.swig b/gnu/llvm/lldb/bindings/python/python-swigsafecast.swig index 091fc29b105..a1e883b3b19 100644 --- a/gnu/llvm/lldb/bindings/python/python-swigsafecast.swig +++ b/gnu/llvm/lldb/bindings/python/python-swigsafecast.swig @@ -1,161 +1,109 @@ -// leaving this undefined ensures we will get a linker error if we try to use SBTypeToSWIGWrapper() -// for a type for which we did not specialze this function -template -PyObject* -SBTypeToSWIGWrapper (SBClass* sb_object); +namespace lldb_private { +namespace python { -template -PyObject* -SBTypeToSWIGWrapper (SBClass& sb_object) -{ - return SBTypeToSWIGWrapper(&sb_object); +PythonObject ToSWIGHelper(void *obj, swig_type_info *info) { + return {PyRefType::Owned, SWIG_NewPointerObj(obj, info, SWIG_POINTER_OWN)}; } -template -PyObject* -SBTypeToSWIGWrapper (const SBClass& sb_object) -{ - return SBTypeToSWIGWrapper(&sb_object); +PythonObject ToSWIGWrapper(std::unique_ptr value_sb) { + return ToSWIGHelper(value_sb.release(), SWIGTYPE_p_lldb__SBValue); } -template <> -PyObject* -SBTypeToSWIGWrapper (PyObject* py_object) -{ - return py_object; +PythonObject ToSWIGWrapper(lldb::ValueObjectSP value_sp) { + return ToSWIGWrapper(std::make_unique(std::move(value_sp))); } -template <> -PyObject* -SBTypeToSWIGWrapper (unsigned int* c_int) -{ - if (!c_int) - return NULL; - return PyInt_FromLong(*c_int); +PythonObject ToSWIGWrapper(lldb::TargetSP target_sp) { + return ToSWIGHelper(new lldb::SBTarget(std::move(target_sp)), + SWIGTYPE_p_lldb__SBTarget); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBEvent* event_sb) -{ - return SWIG_NewPointerObj((void *) event_sb, SWIGTYPE_p_lldb__SBEvent, 0); +PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp) { + return ToSWIGHelper(new lldb::SBProcess(std::move(process_sp)), + SWIGTYPE_p_lldb__SBProcess); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBProcess* process_sb) -{ - return SWIG_NewPointerObj((void *) process_sb, SWIGTYPE_p_lldb__SBProcess, 0); +PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp) { + return ToSWIGHelper(new lldb::SBThreadPlan(std::move(thread_plan_sp)), + SWIGTYPE_p_lldb__SBThreadPlan); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBThread* thread_sb) -{ - return SWIG_NewPointerObj((void *) thread_sb, SWIGTYPE_p_lldb__SBThread, 0); +PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) { + return ToSWIGHelper(new lldb::SBBreakpoint(std::move(breakpoint_sp)), + SWIGTYPE_p_lldb__SBBreakpoint); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBThreadPlan* thread_plan_sb) -{ - return SWIG_NewPointerObj((void *) thread_plan_sb, SWIGTYPE_p_lldb__SBThreadPlan, 0); +PythonObject ToSWIGWrapper(const Status& status) { + return ToSWIGHelper(new lldb::SBError(status), SWIGTYPE_p_lldb__SBError); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBTarget* target_sb) -{ - return SWIG_NewPointerObj((void *) target_sb, SWIGTYPE_p_lldb__SBTarget, 0); +PythonObject ToSWIGWrapper(std::unique_ptr stream_sb) { + return ToSWIGHelper(stream_sb.release(), SWIGTYPE_p_lldb__SBStream); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBFrame* frame_sb) -{ - return SWIG_NewPointerObj((void *) frame_sb, SWIGTYPE_p_lldb__SBFrame, 0); +PythonObject ToSWIGWrapper(std::unique_ptr data_sb) { + return ToSWIGHelper(data_sb.release(), SWIGTYPE_p_lldb__SBStructuredData); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBDebugger* debugger_sb) -{ - return SWIG_NewPointerObj((void *) debugger_sb, SWIGTYPE_p_lldb__SBDebugger, 0); +PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl) { + return ToSWIGWrapper(std::make_unique(data_impl)); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBBreakpoint* breakpoint_sb) -{ - return SWIG_NewPointerObj((void *) breakpoint_sb, SWIGTYPE_p_lldb__SBBreakpoint, 0); +PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp) { + return ToSWIGHelper(new lldb::SBThread(std::move(thread_sp)), + SWIGTYPE_p_lldb__SBThread); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBWatchpoint* watchpoint_sb) -{ - return SWIG_NewPointerObj((void *) watchpoint_sb, SWIGTYPE_p_lldb__SBWatchpoint, 0); +PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp) { + return ToSWIGHelper(new lldb::SBFrame(std::move(frame_sp)), + SWIGTYPE_p_lldb__SBFrame); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBBreakpointLocation* breakpoint_location_sb) -{ - return SWIG_NewPointerObj((void *) breakpoint_location_sb, SWIGTYPE_p_lldb__SBBreakpointLocation, 0); +PythonObject ToSWIGWrapper(lldb::DebuggerSP debugger_sp) { + return ToSWIGHelper(new lldb::SBDebugger(std::move(debugger_sp)), + SWIGTYPE_p_lldb__SBDebugger); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBBreakpointName* breakpoint_name_sb) -{ - return SWIG_NewPointerObj((void *) breakpoint_name_sb, SWIGTYPE_p_lldb__SBBreakpointName, 0); +PythonObject ToSWIGWrapper(lldb::WatchpointSP watchpoint_sp) { + return ToSWIGHelper(new lldb::SBWatchpoint(std::move(watchpoint_sp)), + SWIGTYPE_p_lldb__SBWatchpoint); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBValue* value_sb) -{ - return SWIG_NewPointerObj((void *) value_sb, SWIGTYPE_p_lldb__SBValue, 0); +PythonObject ToSWIGWrapper(lldb::BreakpointLocationSP bp_loc_sp) { + return ToSWIGHelper(new lldb::SBBreakpointLocation(std::move(bp_loc_sp)), + SWIGTYPE_p_lldb__SBBreakpointLocation); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBCommandReturnObject* cmd_ret_obj_sb) -{ - return SWIG_NewPointerObj((void *) cmd_ret_obj_sb, SWIGTYPE_p_lldb__SBCommandReturnObject, 0); +PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp) { + return ToSWIGHelper(new lldb::SBExecutionContext(std::move(ctx_sp)), + SWIGTYPE_p_lldb__SBExecutionContext); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBExecutionContext* ctx_sb) -{ - return SWIG_NewPointerObj((void *) ctx_sb, SWIGTYPE_p_lldb__SBExecutionContext, 0); +PythonObject ToSWIGWrapper(lldb::TypeImplSP type_impl_sp) { + return ToSWIGHelper(new lldb::SBType(type_impl_sp), SWIGTYPE_p_lldb__SBType); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBTypeSummaryOptions* summary_options_sb) -{ - return SWIG_NewPointerObj((void *) summary_options_sb, SWIGTYPE_p_lldb__SBTypeSummaryOptions, 0); +PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options) { + return ToSWIGHelper(new lldb::SBTypeSummaryOptions(summary_options), + SWIGTYPE_p_lldb__SBTypeSummaryOptions); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBStructuredData* structured_data_sb) -{ - return SWIG_NewPointerObj((void *) structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0); +PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx) { + return ToSWIGHelper(new lldb::SBSymbolContext(sym_ctx), + SWIGTYPE_p_lldb__SBSymbolContext); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBSymbolContext* sym_ctx_sb) -{ - return SWIG_NewPointerObj((void *) sym_ctx_sb, SWIGTYPE_p_lldb__SBSymbolContext, 0); +ScopedPythonObject +ToSWIGWrapper(CommandReturnObject &cmd_retobj) { + return ScopedPythonObject( + new lldb::SBCommandReturnObject(cmd_retobj), + SWIGTYPE_p_lldb__SBCommandReturnObject); } -template <> -PyObject* -SBTypeToSWIGWrapper (lldb::SBStream* stream_sb) -{ - return SWIG_NewPointerObj((void *) stream_sb, SWIGTYPE_p_lldb__SBStream, 0); +ScopedPythonObject ToSWIGWrapper(Event *event) { + return ScopedPythonObject(new lldb::SBEvent(event), + SWIGTYPE_p_lldb__SBEvent); } + +} // namespace python +} // namespace lldb_private diff --git a/gnu/llvm/lldb/bindings/python/python-typemaps.h b/gnu/llvm/lldb/bindings/python/python-typemaps.h index b45352ad629..8a533e82298 100644 --- a/gnu/llvm/lldb/bindings/python/python-typemaps.h +++ b/gnu/llvm/lldb/bindings/python/python-typemaps.h @@ -1,6 +1,8 @@ #ifndef LLDB_BINDINGS_PYTHON_PYTHON_TYPEMAPS_H #define LLDB_BINDINGS_PYTHON_PYTHON_TYPEMAPS_H +#include + // Defined here instead of a .swig file because SWIG 2 doesn't support // explicit deleted functions. struct Py_buffer_RAII { diff --git a/gnu/llvm/lldb/bindings/python/python-typemaps.swig b/gnu/llvm/lldb/bindings/python/python-typemaps.swig index b1ace4ff3b1..11f68d59ae7 100644 --- a/gnu/llvm/lldb/bindings/python/python-typemaps.swig +++ b/gnu/llvm/lldb/bindings/python/python-typemaps.swig @@ -12,23 +12,23 @@ PythonList list(PyRefType::Borrowed, $input); int size = list.GetSize(); int i = 0; - $1 = (char**)malloc((size+1)*sizeof(char*)); + $1 = (char **)malloc((size + 1) * sizeof(char *)); for (i = 0; i < size; i++) { PythonString py_str = list.GetItemAtIndex(i).AsType(); if (!py_str.IsAllocated()) { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); + PyErr_SetString(PyExc_TypeError, "list must contain strings"); free($1); - return nullptr; + SWIG_fail; } - $1[i] = const_cast(py_str.GetString().data()); + $1[i] = const_cast(py_str.GetString().data()); } $1[i] = 0; } else if ($input == Py_None) { - $1 = NULL; + $1 = NULL; } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; + PyErr_SetString(PyExc_TypeError, "not a list"); + SWIG_fail; } } @@ -41,12 +41,12 @@ int i = 0; for (i = 0; i < size; i++) { PythonString s = list.GetItemAtIndex(i).AsType(); - if (!s.IsAllocated()) { $1 = 0; } + if (!s.IsAllocated()) { + $1 = 0; + } } - } - else - { - $1 = ( ($input == Py_None) ? 1 : 0); + } else { + $1 = (($input == Py_None) ? 1 : 0); } } @@ -58,7 +58,8 @@ int len; int i; len = 0; - while ($1[len]) len++; + while ($1[len]) + len++; PythonList list(len); for (i = 0; i < len; i++) list.SetItemAtIndex(i, PythonString($1[i])); @@ -69,19 +70,19 @@ PythonObject obj = Retain($input); lldb::tid_t value = unwrapOrSetPythonException(As(obj)); if (PyErr_Occurred()) - return nullptr; + SWIG_fail; $1 = value; } %typemap(in) lldb::StateType { PythonObject obj = Retain($input); unsigned long long state_type_value = - unwrapOrSetPythonException(As(obj)); + unwrapOrSetPythonException(As(obj)); if (PyErr_Occurred()) - return nullptr; + SWIG_fail; if (state_type_value > lldb::StateType::kLastStateType) { PyErr_SetString(PyExc_ValueError, "Not a valid StateType value"); - return nullptr; + SWIG_fail; } $1 = static_cast(state_type_value); } @@ -90,16 +91,16 @@ // typemap for a char buffer %typemap(in) (char *dst, size_t dst_len) { - if (!PyInt_Check($input)) { - PyErr_SetString(PyExc_ValueError, "Expecting an integer"); - return NULL; - } - $2 = PyInt_AsLong($input); - if ($2 <= 0) { - PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; - } - $1 = (char *) malloc($2); + if (!PyInt_Check($input)) { + PyErr_SetString(PyExc_ValueError, "Expecting an integer"); + SWIG_fail; + } + $2 = PyInt_AsLong($input); + if ($2 <= 0) { + PyErr_SetString(PyExc_ValueError, "Positive integer expected"); + SWIG_fail; + } + $1 = (char *)malloc($2); } // SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated // as char data instead of byte data. @@ -107,17 +108,17 @@ // Return the char buffer. Discarding any previous return result %typemap(argout) (char *dst, size_t dst_len) { - Py_XDECREF($result); /* Blow away any previous result */ - if (result == 0) { - PythonString string(""); - $result = string.release(); - Py_INCREF($result); - } else { - llvm::StringRef ref(static_cast($1), result); - PythonString string(ref); - $result = string.release(); - } - free($1); + Py_XDECREF($result); /* Blow away any previous result */ + if (result == 0) { + PythonString string(""); + $result = string.release(); + Py_INCREF($result); + } else { + llvm::StringRef ref(static_cast($1), result); + PythonString string(ref); + $result = string.release(); + } + free($1); } // SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated // as char data instead of byte data. @@ -126,23 +127,23 @@ // typemap for handling an snprintf-like API like SBThread::GetStopDescription. %typemap(in) (char *dst_or_null, size_t dst_len) { - if (!PyInt_Check($input)) { - PyErr_SetString(PyExc_ValueError, "Expecting an integer"); - return NULL; - } - $2 = PyInt_AsLong($input); - if ($2 <= 0) { - PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; - } - $1 = (char *) malloc($2); + if (!PyInt_Check($input)) { + PyErr_SetString(PyExc_ValueError, "Expecting an integer"); + SWIG_fail; + } + $2 = PyInt_AsLong($input); + if ($2 <= 0) { + PyErr_SetString(PyExc_ValueError, "Positive integer expected"); + SWIG_fail; + } + $1 = (char *)malloc($2); } %typemap(argout) (char *dst_or_null, size_t dst_len) { - Py_XDECREF($result); /* Blow away any previous result */ - llvm::StringRef ref($1); - PythonString string(ref); - $result = string.release(); - free($1); + Py_XDECREF($result); /* Blow away any previous result */ + llvm::StringRef ref($1); + PythonString string(ref); + $result = string.release(); + free($1); } @@ -151,80 +152,74 @@ // Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len). %typemap(in) (const char *cstr, uint32_t cstr_len), (const char *src, size_t src_len) { - if (PythonString::Check($input)) { - PythonString str(PyRefType::Borrowed, $input); - $1 = (char*)str.GetString().data(); - $2 = str.GetSize(); - } - else if(PythonByteArray::Check($input)) { - PythonByteArray bytearray(PyRefType::Borrowed, $input); - $1 = (char*)bytearray.GetBytes().data(); - $2 = bytearray.GetSize(); - } - else if (PythonBytes::Check($input)) { - PythonBytes bytes(PyRefType::Borrowed, $input); - $1 = (char*)bytes.GetBytes().data(); - $2 = bytes.GetSize(); - } - else { - PyErr_SetString(PyExc_ValueError, "Expecting a string"); - return NULL; - } + if (PythonString::Check($input)) { + PythonString str(PyRefType::Borrowed, $input); + $1 = (char *)str.GetString().data(); + $2 = str.GetSize(); + } else if (PythonByteArray::Check($input)) { + PythonByteArray bytearray(PyRefType::Borrowed, $input); + $1 = (char *)bytearray.GetBytes().data(); + $2 = bytearray.GetSize(); + } else if (PythonBytes::Check($input)) { + PythonBytes bytes(PyRefType::Borrowed, $input); + $1 = (char *)bytes.GetBytes().data(); + $2 = bytes.GetSize(); + } else { + PyErr_SetString(PyExc_ValueError, "Expecting a string"); + SWIG_fail; + } } // For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput. %typemap(in) (const void *buf, size_t size), (const void *data, size_t data_len) { - if (PythonString::Check($input)) { - PythonString str(PyRefType::Borrowed, $input); - $1 = (void*)str.GetString().data(); - $2 = str.GetSize(); - } - else if(PythonByteArray::Check($input)) { - PythonByteArray bytearray(PyRefType::Borrowed, $input); - $1 = (void*)bytearray.GetBytes().data(); - $2 = bytearray.GetSize(); - } - else if (PythonBytes::Check($input)) { - PythonBytes bytes(PyRefType::Borrowed, $input); - $1 = (void*)bytes.GetBytes().data(); - $2 = bytes.GetSize(); - } - else { - PyErr_SetString(PyExc_ValueError, "Expecting a buffer"); - return NULL; - } + if (PythonString::Check($input)) { + PythonString str(PyRefType::Borrowed, $input); + $1 = (void *)str.GetString().data(); + $2 = str.GetSize(); + } else if (PythonByteArray::Check($input)) { + PythonByteArray bytearray(PyRefType::Borrowed, $input); + $1 = (void *)bytearray.GetBytes().data(); + $2 = bytearray.GetSize(); + } else if (PythonBytes::Check($input)) { + PythonBytes bytes(PyRefType::Borrowed, $input); + $1 = (void *)bytes.GetBytes().data(); + $2 = bytes.GetSize(); + } else { + PyErr_SetString(PyExc_ValueError, "Expecting a buffer"); + SWIG_fail; + } } // typemap for an incoming buffer // See also SBProcess::ReadMemory. %typemap(in) (void *buf, size_t size) { - if (PyInt_Check($input)) { - $2 = PyInt_AsLong($input); - } else if (PyLong_Check($input)) { - $2 = PyLong_AsLong($input); - } else { - PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object"); - return NULL; - } - if ($2 <= 0) { - PyErr_SetString(PyExc_ValueError, "Positive integer expected"); - return NULL; - } - $1 = (void *) malloc($2); + if (PyInt_Check($input)) { + $2 = PyInt_AsLong($input); + } else if (PyLong_Check($input)) { + $2 = PyLong_AsLong($input); + } else { + PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object"); + SWIG_fail; + } + if ($2 <= 0) { + PyErr_SetString(PyExc_ValueError, "Positive integer expected"); + SWIG_fail; + } + $1 = (void *)malloc($2); } // Return the buffer. Discarding any previous return result // See also SBProcess::ReadMemory. %typemap(argout) (void *buf, size_t size) { - Py_XDECREF($result); /* Blow away any previous result */ - if (result == 0) { - $result = Py_None; - Py_INCREF($result); - } else { - PythonBytes bytes(static_cast($1), result); - $result = bytes.release(); - } - free($1); + Py_XDECREF($result); /* Blow away any previous result */ + if (result == 0) { + $result = Py_None; + Py_INCREF($result); + } else { + PythonBytes bytes(static_cast($1), result); + $result = bytes.release(); + } + free($1); } %{ @@ -250,19 +245,18 @@ template <> int32_t PyLongAsT(PyObject *obj) { return static_cast(PyLong_AsLong(obj)); } -template -bool SetNumberFromPyObject(T &number, PyObject *obj) { +template bool SetNumberFromPyObject(T &number, PyObject *obj) { if (PyInt_Check(obj)) number = static_cast(PyInt_AsLong(obj)); else if (PyLong_Check(obj)) number = PyLongAsT(obj); - else return false; + else + return false; return true; } -template <> -bool SetNumberFromPyObject(double &number, PyObject *obj) { +template <> bool SetNumberFromPyObject(double &number, PyObject *obj) { if (PyFloat_Check(obj)) { number = PyFloat_AsDouble(obj); return true; @@ -287,26 +281,26 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { int size = PyList_Size($input); int i = 0; $2 = size; - $1 = ($1_type) malloc(size * sizeof($*1_type)); + $1 = ($1_type)malloc(size * sizeof($*1_type)); for (i = 0; i < size; i++) { - PyObject *o = PyList_GetItem($input,i); + PyObject *o = PyList_GetItem($input, i); if (!SetNumberFromPyObject($1[i], o)) { - PyErr_SetString(PyExc_TypeError,"list must contain numbers"); + PyErr_SetString(PyExc_TypeError, "list must contain numbers"); free($1); - return NULL; + SWIG_fail; } if (PyErr_Occurred()) { free($1); - return NULL; + SWIG_fail; } } } else if ($input == Py_None) { - $1 = NULL; + $1 = NULL; $2 = 0; } else { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; + PyErr_SetString(PyExc_TypeError, "not a list"); + SWIG_fail; } } @@ -322,45 +316,44 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { // to the more Pythonic style where a list is returned and no previous allocation // is necessary - this will break if more than 50 versions are ever returned %typemap(typecheck) (uint32_t *versions, uint32_t num_versions) { - $1 = ($input == Py_None ? 1 : 0); + $1 = ($input == Py_None ? 1 : 0); } %typemap(in, numinputs=0) (uint32_t *versions) { - $1 = (uint32_t*)malloc(sizeof(uint32_t) * 50); + $1 = (uint32_t *)malloc(sizeof(uint32_t) * 50); } %typemap(in, numinputs=0) (uint32_t num_versions) { - $1 = 50; + $1 = 50; } %typemap(argout) (uint32_t *versions, uint32_t num_versions) { - uint32_t count = result; - if (count >= $2) - count = $2; - PyObject* list = PyList_New(count); - for (uint32_t j = 0; j < count; j++) - { - PyObject* item = PyInt_FromLong($1[j]); - int ok = PyList_SetItem(list,j,item); - if (ok != 0) - { - $result = Py_None; - break; - } + uint32_t count = result; + if (count >= $2) + count = $2; + PyObject *list = PyList_New(count); + for (uint32_t j = 0; j < count; j++) { + PyObject *item = PyInt_FromLong($1[j]); + int ok = PyList_SetItem(list, j, item); + if (ok != 0) { + $result = Py_None; + break; } - $result = list; + } + $result = list; } %typemap(freearg) (uint32_t *versions) { - free($1); + free($1); } // For Log::LogOutputCallback %typemap(in) (lldb::LogOutputCallback log_callback, void *baton) { - if (!($input == Py_None || PyCallable_Check(reinterpret_cast($input)))) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast($input)))) { PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - return NULL; + SWIG_fail; } // FIXME (filcab): We can't currently check if our callback is already @@ -376,7 +369,7 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { %typemap(typecheck) (lldb::LogOutputCallback log_callback, void *baton) { $1 = $input == Py_None; - $1 = $1 || PyCallable_Check(reinterpret_cast($input)); + $1 = $1 || PyCallable_Check(reinterpret_cast($input)); } @@ -384,11 +377,11 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } auto sp = unwrapOrSetPythonException(py_file.ConvertToFile()); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -396,11 +389,12 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } - auto sp = unwrapOrSetPythonException(py_file.ConvertToFileForcingUseOfScriptingIOMethods()); + auto sp = unwrapOrSetPythonException( + py_file.ConvertToFileForcingUseOfScriptingIOMethods()); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -408,11 +402,12 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } - auto sp = unwrapOrSetPythonException(py_file.ConvertToFile(/*borrowed=*/true)); + auto sp = + unwrapOrSetPythonException(py_file.ConvertToFile(/*borrowed=*/true)); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -420,11 +415,12 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); - return nullptr; + SWIG_fail; } - auto sp = unwrapOrSetPythonException(py_file.ConvertToFileForcingUseOfScriptingIOMethods(/*borrowed=*/true)); + auto sp = unwrapOrSetPythonException( + py_file.ConvertToFileForcingUseOfScriptingIOMethods(/*borrowed=*/true)); if (!sp) - return nullptr; + SWIG_fail; $1 = sp; } @@ -439,47 +435,41 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { %typemap(out) lldb::FileSP { $result = nullptr; - lldb::FileSP &sp = $1; + const lldb::FileSP &sp = $1; if (sp) { PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); if (!pyfile.IsValid()) - return nullptr; + SWIG_fail; $result = pyfile.release(); } - if (!$result) - { - $result = Py_None; - Py_INCREF(Py_None); + if (!$result) { + $result = Py_None; + Py_INCREF(Py_None); } } %typemap(in) (const char* string, int len) { - if ($input == Py_None) - { - $1 = NULL; - $2 = 0; - } - else if (PythonString::Check($input)) - { - PythonString py_str(PyRefType::Borrowed, $input); - llvm::StringRef str = py_str.GetString(); - $1 = const_cast(str.data()); - $2 = str.size(); - // In Python 2, if $input is a PyUnicode object then this - // will trigger a Unicode -> String conversion, in which - // case the `PythonString` will now own the PyString. Thus - // if it goes out of scope, the data will be deleted. The - // only way to avoid this is to leak the Python object in - // that case. Note that if there was no conversion, then - // releasing the string will not leak anything, since we - // created this as a borrowed reference. - py_str.release(); - } - else - { - PyErr_SetString(PyExc_TypeError,"not a string-like object"); - return NULL; - } + if ($input == Py_None) { + $1 = NULL; + $2 = 0; + } else if (PythonString::Check($input)) { + PythonString py_str(PyRefType::Borrowed, $input); + llvm::StringRef str = py_str.GetString(); + $1 = const_cast(str.data()); + $2 = str.size(); + // In Python 2, if $input is a PyUnicode object then this + // will trigger a Unicode -> String conversion, in which + // case the `PythonString` will now own the PyString. Thus + // if it goes out of scope, the data will be deleted. The + // only way to avoid this is to leak the Python object in + // that case. Note that if there was no conversion, then + // releasing the string will not leak anything, since we + // created this as a borrowed reference. + py_str.release(); + } else { + PyErr_SetString(PyExc_TypeError, "not a string-like object"); + SWIG_fail; + } } // These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, @@ -491,7 +481,9 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { %define %pybuffer_mutable_binary(TYPEMAP, SIZE) %typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { - int res; Py_ssize_t size = 0; void *buf = 0; + int res; + Py_ssize_t size = 0; + void *buf = 0; res = PyObject_GetBuffer($input, &view.buffer, PyBUF_WRITABLE); if (res < 0) { PyErr_Clear(); @@ -499,14 +491,16 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { } size = view.buffer.len; buf = view.buffer.buf; - $1 = ($1_ltype) buf; - $2 = ($2_ltype) (size/sizeof($*1_type)); + $1 = ($1_ltype)buf; + $2 = ($2_ltype)(size / sizeof($*1_type)); } %enddef %define %pybuffer_binary(TYPEMAP, SIZE) %typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { - int res; Py_ssize_t size = 0; const void *buf = 0; + int res; + Py_ssize_t size = 0; + const void *buf = 0; res = PyObject_GetBuffer($input, &view.buffer, PyBUF_CONTIG_RO); if (res < 0) { PyErr_Clear(); @@ -514,8 +508,8 @@ bool SetNumberFromPyObject(double &number, PyObject *obj) { } size = view.buffer.len; buf = view.buffer.buf; - $1 = ($1_ltype) buf; - $2 = ($2_ltype) (size / sizeof($*1_type)); + $1 = ($1_ltype)buf; + $2 = ($2_ltype)(size / sizeof($*1_type)); } %enddef diff --git a/gnu/llvm/lldb/bindings/python/python-wrapper.swig b/gnu/llvm/lldb/bindings/python/python-wrapper.swig index 4c39e9c2c77..9a08c3000b7 100644 --- a/gnu/llvm/lldb/bindings/python/python-wrapper.swig +++ b/gnu/llvm/lldb/bindings/python/python-wrapper.swig @@ -1,1304 +1,1041 @@ %header %{ -template -PyObject * -SBTypeToSWIGWrapper (T* item); - -class PyErr_Cleaner -{ +class PyErr_Cleaner { public: - PyErr_Cleaner(bool print=false) : - m_print(print) - { - } + PyErr_Cleaner(bool print = false) : m_print(print) {} - ~PyErr_Cleaner() - { - if (PyErr_Occurred()) - { - if(m_print && !PyErr_ExceptionMatches(PyExc_SystemExit)) - PyErr_Print(); - PyErr_Clear(); - } + ~PyErr_Cleaner() { + if (PyErr_Occurred()) { + if (m_print && !PyErr_ExceptionMatches(PyExc_SystemExit)) + PyErr_Print(); + PyErr_Clear(); } + } private: - bool m_print; + bool m_print; }; -%} +llvm::Expected lldb_private::LLDBSwigPythonBreakpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &frame_sp, + const lldb::BreakpointLocationSP &bp_loc_sp, + const lldb_private::StructuredDataImpl &args_impl) { + using namespace llvm; -%wrapper %{ + lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); -// resolve a dotted Python name in the form -// foo.bar.baz.Foobar to an actual Python object -// if pmodule is NULL, the __main__ module will be used -// as the starting point for the search + PyErr_Cleaner py_err_cleaner(true); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); + unsigned max_positional_args; + if (auto arg_info = pfunc.GetArgInfo()) + max_positional_args = arg_info.get().max_positional_args; + else + return arg_info.takeError(); -// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...) -// and is used when a script command is attached to a breakpoint for execution. - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" - -// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has -// C-linkage specified, but returns UDT 'llvm::Expected' which is -// incompatible with C -#if _MSC_VER -#pragma warning (push) -#pragma warning (disable : 4190) -#endif - -SWIGEXPORT llvm::Expected -LLDBSwigPythonBreakpointCallbackFunction -( - const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::BreakpointLocationSP& bp_loc_sp, - lldb_private::StructuredDataImpl *args_impl -) -{ - using namespace llvm; - - lldb::SBFrame sb_frame (frame_sp); - lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); - - PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); - - unsigned max_positional_args; - if (auto arg_info = pfunc.GetArgInfo()) - max_positional_args = arg_info.get().max_positional_args; - else - return arg_info.takeError(); - - PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame)); - PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc)); - - auto result = [&] () -> Expected { - // If the called function doesn't take extra_args, drop them here: - if (max_positional_args < 4) { - return pfunc.Call(frame_arg, bp_loc_arg, dict); - } else { - lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); - PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); - return pfunc.Call(frame_arg, bp_loc_arg, args_arg, dict); - } - } (); - - if (!result) - return result.takeError(); - - // Only False counts as false! - return result.get().get() != Py_False; -} + PythonObject frame_arg = ToSWIGWrapper(frame_sp); + PythonObject bp_loc_arg = ToSWIGWrapper(bp_loc_sp); -#if _MSC_VER -#pragma warning (pop) -#endif + auto result = + max_positional_args < 4 + ? pfunc.Call(frame_arg, bp_loc_arg, dict) + : pfunc.Call(frame_arg, bp_loc_arg, ToSWIGWrapper(args_impl), dict); -#pragma clang diagnostic pop + if (!result) + return result.takeError(); -// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...) -// and is used when a script command is attached to a watchpoint for execution. + // Only False counts as false! + return result.get().get() != Py_False; +} -SWIGEXPORT bool -LLDBSwigPythonWatchpointCallbackFunction -( - const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::WatchpointSP& wp_sp -) -{ - lldb::SBFrame sb_frame (frame_sp); - lldb::SBWatchpoint sb_wp(wp_sp); +// resolve a dotted Python name in the form +// foo.bar.baz.Foobar to an actual Python object +// if pmodule is NULL, the __main__ module will be used +// as the starting point for the search - bool stop_at_watchpoint = true; +// This function is called by +// lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...) and is +// used when a script command is attached to a breakpoint for execution. - PyErr_Cleaner py_err_cleaner(true); +// This function is called by +// lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...) and is +// used when a script command is attached to a watchpoint for execution. - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); +bool lldb_private::LLDBSwigPythonWatchpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &frame_sp, const lldb::WatchpointSP &wp_sp) { - if (!pfunc.IsAllocated()) - return stop_at_watchpoint; + bool stop_at_watchpoint = true; - PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame)); - PythonObject wp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_wp)); - PythonObject result = pfunc(frame_arg, wp_arg, dict); + PyErr_Cleaner py_err_cleaner(true); - if (result.get() == Py_False) - stop_at_watchpoint = false; + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); + if (!pfunc.IsAllocated()) return stop_at_watchpoint; -} -SWIGEXPORT bool -LLDBSwigPythonCallTypeScript -( - const char *python_function_name, - const void *session_dictionary, - const lldb::ValueObjectSP& valobj_sp, - void** pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP& options_sp, - std::string& retval -) -{ - lldb::SBValue sb_value (valobj_sp); - lldb::SBTypeSummaryOptions sb_options(options_sp.get()); - - retval.clear(); - - if (!python_function_name || !session_dictionary) - return false; - - PyObject *pfunc_impl = nullptr; - - if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper)) - { - pfunc_impl = (PyObject*)(*pyfunct_wrapper); - if (pfunc_impl->ob_refcnt == 1) - { - Py_XDECREF(pfunc_impl); - pfunc_impl = NULL; - } - } + PythonObject result = + pfunc(ToSWIGWrapper(frame_sp), ToSWIGWrapper(wp_sp), dict); - PyObject *py_dict = (PyObject*)session_dictionary; - if (!PythonDictionary::Check(py_dict)) - return true; + if (result.get() == Py_False) + stop_at_watchpoint = false; - PythonDictionary dict(PyRefType::Borrowed, py_dict); + return stop_at_watchpoint; +} - PyErr_Cleaner pyerr_cleanup(true); // show Python errors +// This function is called by +// ScriptInterpreterPython::FormatterMatchingCallbackFunction and it's used when +// a data formatter provides the name of a callback to inspect a candidate type +// before considering a match. +bool lldb_private::LLDBSwigPythonFormatterCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + lldb::TypeImplSP type_impl_sp) { - PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl); + PyErr_Cleaner py_err_cleaner(true); - if (!pfunc.IsAllocated()) - { - pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); - if (!pfunc.IsAllocated()) - return false; - - if (pyfunct_wrapper) - { - *pyfunct_wrapper = pfunc.get(); - Py_XINCREF(pfunc.get()); - } - } + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - PythonObject result; - auto argc = pfunc.GetArgInfo(); - if (!argc) { - llvm::consumeError(argc.takeError()); - return false; - } + if (!pfunc.IsAllocated()) + return false; - PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value)); - PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options)); + PythonObject result = + pfunc(ToSWIGWrapper(type_impl_sp), dict); - if (argc.get().max_positional_args < 3) - result = pfunc(value_arg,dict); - else - result = pfunc(value_arg,dict,options_arg); + // Only if everything goes okay and the function returns True we'll consider + // it a match. + return result.get() == Py_True; +} - retval = result.Str().GetString().str(); +bool lldb_private::LLDBSwigPythonCallTypeScript( + const char *python_function_name, const void *session_dictionary, + const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval) { - return true; -} + retval.clear(); -SWIGEXPORT void* -LLDBSwigPythonCreateSyntheticProvider -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP& valobj_sp -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; + if (!python_function_name || !session_dictionary) + return false; - PyErr_Cleaner py_err_cleaner(true); + PyObject *pfunc_impl = nullptr; - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name,dict); + if (pyfunct_wrapper && *pyfunct_wrapper && + PyFunction_Check(*pyfunct_wrapper)) { + pfunc_impl = (PyObject *)(*pyfunct_wrapper); + if (pfunc_impl->ob_refcnt == 1) { + Py_XDECREF(pfunc_impl); + pfunc_impl = NULL; + } + } - if (!pfunc.IsAllocated()) - Py_RETURN_NONE; + PyObject *py_dict = (PyObject *)session_dictionary; + if (!PythonDictionary::Check(py_dict)) + return true; - // I do not want the SBValue to be deallocated when going out of scope because python - // has ownership of it and will manage memory for this object by itself - lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp); - sb_value->SetPreferSyntheticValue(false); + PythonDictionary dict(PyRefType::Borrowed, py_dict); - PythonObject val_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value)); - if (!val_arg.IsAllocated()) - Py_RETURN_NONE; + PyErr_Cleaner pyerr_cleanup(true); // show Python errors - PythonObject result = pfunc(val_arg, dict); + PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl); - if (result.IsAllocated()) - return result.release(); + if (!pfunc.IsAllocated()) { + pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); + if (!pfunc.IsAllocated()) + return false; - Py_RETURN_NONE; -} + if (pyfunct_wrapper) { + *pyfunct_wrapper = pfunc.get(); + Py_XINCREF(pfunc.get()); + } + } -SWIGEXPORT void* -LLDBSwigPythonCreateCommandObject -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::DebuggerSP debugger_sp -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); + PythonObject result; + auto argc = pfunc.GetArgInfo(); + if (!argc) { + llvm::consumeError(argc.takeError()); + return false; + } - if (!pfunc.IsAllocated()) - return nullptr; + PythonObject value_arg = ToSWIGWrapper(valobj_sp); - lldb::SBDebugger debugger_sb(debugger_sp); - PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); - PythonObject result = pfunc(debugger_arg, dict); + if (argc.get().max_positional_args < 3) + result = pfunc(value_arg, dict); + else + result = pfunc(value_arg, dict, ToSWIGWrapper(*options_sp)); - if (result.IsAllocated()) - return result.release(); + retval = result.Str().GetString().str(); - Py_RETURN_NONE; + return true; } -SWIGEXPORT void* -LLDBSwigPythonCreateScriptedProcess -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::TargetSP& target_sp, - lldb_private::StructuredDataImpl *args_impl, - std::string &error_string -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); - - if (!pfunc.IsAllocated()) { - error_string.append("could not find script class: "); - error_string.append(python_class_name); - return nullptr; - } +PythonObject lldb_private::LLDBSwigPythonCreateSyntheticProvider( + const char *python_class_name, const char *session_dictionary_name, + const lldb::ValueObjectSP &valobj_sp) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); - // I do not want the SBTarget to be deallocated when going out of scope - // because python has ownership of it and will manage memory for this - // object by itself - PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBTarget(target_sp))); - - if (!target_arg.IsAllocated()) - Py_RETURN_NONE; - - llvm::Expected arg_info = pfunc.GetArgInfo(); - if (!arg_info) { - llvm::handleAllErrors( - arg_info.takeError(), - [&](PythonException &E) { - error_string.append(E.ReadBacktrace()); - }, - [&](const llvm::ErrorInfoBase &E) { - error_string.append(E.message()); - }); - Py_RETURN_NONE; - } + PyErr_Cleaner py_err_cleaner(true); - PythonObject result = {}; - if (arg_info.get().max_positional_args == 2) { - if (args_impl != nullptr) { - error_string.assign("args passed, but __init__ does not take an args dictionary"); - Py_RETURN_NONE; - } - result = pfunc(target_arg, dict); - } else if (arg_info.get().max_positional_args >= 3) { - PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl))); - result = pfunc(target_arg, args_arg, dict); - } else { - error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)"); - Py_RETURN_NONE; - } + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); - if (result.IsAllocated()) - return result.release(); - Py_RETURN_NONE; -} + if (!pfunc.IsAllocated()) + return PythonObject(); -SWIGEXPORT void* -LLDBSwigPythonCreateScriptedThreadPlan -( - const char *python_class_name, - const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args_impl, - std::string &error_string, - const lldb::ThreadPlanSP& thread_plan_sp -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); - - if (!pfunc.IsAllocated()) { - error_string.append("could not find script class: "); - error_string.append(python_class_name); - return nullptr; - } + auto sb_value = std::make_unique(valobj_sp); + sb_value->SetPreferSyntheticValue(false); - // I do not want the SBThreadPlan to be deallocated when going out of scope - // because python has ownership of it and will manage memory for this - // object by itself - PythonObject tp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBThreadPlan(thread_plan_sp))); - - if (!tp_arg.IsAllocated()) - Py_RETURN_NONE; - - llvm::Expected arg_info = pfunc.GetArgInfo(); - if (!arg_info) { - llvm::handleAllErrors( - arg_info.takeError(), - [&](PythonException &E) { - error_string.append(E.ReadBacktrace()); - }, - [&](const llvm::ErrorInfoBase &E) { - error_string.append(E.message()); - }); - Py_RETURN_NONE; - } + PythonObject val_arg = ToSWIGWrapper(std::move(sb_value)); + if (!val_arg.IsAllocated()) + return PythonObject(); - PythonObject result = {}; - if (arg_info.get().max_positional_args == 2) { - if (args_impl != nullptr) { - error_string.assign("args passed, but __init__ does not take an args dictionary"); - Py_RETURN_NONE; - } - result = pfunc(tp_arg, dict); - } else if (arg_info.get().max_positional_args >= 3) { - PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl))); - result = pfunc(tp_arg, args_arg, dict); - } else { - error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)"); - Py_RETURN_NONE; - } + PythonObject result = pfunc(val_arg, dict); - // FIXME: At this point we should check that the class we found supports all the methods - // that we need. + if (result.IsAllocated()) + return result; - if (result.IsAllocated()) - return result.release(); - Py_RETURN_NONE; + return PythonObject(); } -SWIGEXPORT bool -LLDBSWIGPythonCallThreadPlan -( - void *implementor, - const char *method_name, - lldb_private::Event *event, - bool &got_error -) -{ - got_error = false; - - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName(method_name); +PythonObject lldb_private::LLDBSwigPythonCreateCommandObject( + const char *python_class_name, const char *session_dictionary_name, + lldb::DebuggerSP debugger_sp) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); - if (!pfunc.IsAllocated()) - return false; - - PythonObject result; - if (event != nullptr) - { - lldb::SBEvent sb_event(event); - PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event)); - result = pfunc(event_arg); - } - else - result = pfunc(); + PyErr_Cleaner py_err_cleaner(true); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); - if (PyErr_Occurred()) - { - got_error = true; - printf ("Return value was neither false nor true for call to %s.\n", method_name); - PyErr_Print(); - return false; - } - - if (result.get() == Py_True) - return true; - else if (result.get() == Py_False) - return false; + if (!pfunc.IsAllocated()) + return PythonObject(); - // Somebody returned the wrong thing... - got_error = true; - printf ("Wrong return value type for call to %s.\n", method_name); - return false; + return pfunc(ToSWIGWrapper(std::move(debugger_sp)), dict); } -SWIGEXPORT void * -LLDBSwigPythonCreateScriptedBreakpointResolver -( - const char *python_class_name, - const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args_impl, - lldb::BreakpointSP &breakpoint_sp -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; +PythonObject lldb_private::LLDBSwigPythonCreateScriptedObject( + const char *python_class_name, const char *session_dictionary_name, + lldb::ExecutionContextRefSP exe_ctx_sp, + const lldb_private::StructuredDataImpl &args_impl, + std::string &error_string) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); + + PyErr_Cleaner py_err_cleaner(true); + + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); + + if (!pfunc.IsAllocated()) { + error_string.append("could not find script class: "); + error_string.append(python_class_name); + return PythonObject(); + } + + llvm::Expected arg_info = pfunc.GetArgInfo(); + if (!arg_info) { + llvm::handleAllErrors( + arg_info.takeError(), + [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, + [&](const llvm::ErrorInfoBase &E) { + error_string.append(E.message()); + }); + return PythonObject(); + } + + PythonObject result = {}; + if (arg_info.get().max_positional_args == 2) { + result = pfunc(ToSWIGWrapper(exe_ctx_sp), ToSWIGWrapper(args_impl)); + } else { + error_string.assign("wrong number of arguments in __init__, should be 2 " + "(not including self)"); + } + return result; +} - PyErr_Cleaner py_err_cleaner(true); +PythonObject lldb_private::LLDBSwigPythonCreateScriptedThreadPlan( + const char *python_class_name, const char *session_dictionary_name, + const lldb_private::StructuredDataImpl &args_impl, + std::string &error_string, const lldb::ThreadPlanSP &thread_plan_sp) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); + + PyErr_Cleaner py_err_cleaner(true); + + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); + + if (!pfunc.IsAllocated()) { + error_string.append("could not find script class: "); + error_string.append(python_class_name); + return PythonObject(); + } + + PythonObject tp_arg = ToSWIGWrapper(thread_plan_sp); + + llvm::Expected arg_info = pfunc.GetArgInfo(); + if (!arg_info) { + llvm::handleAllErrors( + arg_info.takeError(), + [&](PythonException &E) { error_string.append(E.ReadBacktrace()); }, + [&](const llvm::ErrorInfoBase &E) { + error_string.append(E.message()); + }); + return PythonObject(); + } + + PythonObject result = {}; + auto args_sb = std::make_unique(args_impl); + if (arg_info.get().max_positional_args == 2) { + if (args_sb->IsValid()) { + error_string.assign( + "args passed, but __init__ does not take an args dictionary"); + return PythonObject(); + } + result = pfunc(tp_arg, dict); + } else if (arg_info.get().max_positional_args >= 3) { + result = pfunc(tp_arg, ToSWIGWrapper(std::move(args_sb)), dict); + } else { + error_string.assign("wrong number of arguments in __init__, should be 2 or " + "3 (not including self)"); + return PythonObject(); + } + + // FIXME: At this point we should check that the class we found supports all + // the methods that we need. + + return result; +} - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); +bool lldb_private::LLDBSWIGPythonCallThreadPlan( + void *implementor, const char *method_name, lldb_private::Event *event, + bool &got_error) { + got_error = false; - if (!pfunc.IsAllocated()) - return nullptr; + PyErr_Cleaner py_err_cleaner(false); + PythonObject self(PyRefType::Borrowed, static_cast(implementor)); + auto pfunc = self.ResolveName(method_name); - lldb::SBBreakpoint *bkpt_value = new lldb::SBBreakpoint(breakpoint_sp); + if (!pfunc.IsAllocated()) + return false; - PythonObject bkpt_arg(PyRefType::Owned, SBTypeToSWIGWrapper(bkpt_value)); + PythonObject result; + if (event != nullptr) { + ScopedPythonObject event_arg = ToSWIGWrapper(event); + result = pfunc(event_arg.obj()); + } else + result = pfunc(); - lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); - PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); + if (PyErr_Occurred()) { + got_error = true; + printf("Return value was neither false nor true for call to %s.\n", + method_name); + PyErr_Print(); + return false; + } - PythonObject result = pfunc(bkpt_arg, args_arg, dict); - // FIXME: At this point we should check that the class we found supports all the methods - // that we need. + if (result.get() == Py_True) + return true; + else if (result.get() == Py_False) + return false; - if (result.IsAllocated()) - { - // Check that __callback__ is defined: - auto callback_func = result.ResolveName("__callback__"); - if (callback_func.IsAllocated()) - return result.release(); - else - result.release(); - } - Py_RETURN_NONE; + // Somebody returned the wrong thing... + got_error = true; + printf("Wrong return value type for call to %s.\n", method_name); + return false; } -SWIGEXPORT unsigned int -LLDBSwigPythonCallBreakpointResolver -( - void *implementor, - const char *method_name, - lldb_private::SymbolContext *sym_ctx -) -{ - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName(method_name); - - if (!pfunc.IsAllocated()) - return 0; - - PythonObject result; - if (sym_ctx != nullptr) { - lldb::SBSymbolContext sb_sym_ctx(sym_ctx); - PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx)); - result = pfunc(sym_ctx_arg); - } else - result = pfunc(); - - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - return 0; - } - - // The callback will return a bool, but we're need to also return ints - // so we're squirrelling the bool through as an int... And if you return - // nothing, we'll continue. - if (strcmp(method_name, "__callback__") == 0) { - if (result.get() == Py_False) - return 0; - else - return 1; - } +PythonObject lldb_private::LLDBSwigPythonCreateScriptedBreakpointResolver( + const char *python_class_name, const char *session_dictionary_name, + const StructuredDataImpl &args_impl, + const lldb::BreakpointSP &breakpoint_sp) { + + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); + + PyErr_Cleaner py_err_cleaner(true); + + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); + + if (!pfunc.IsAllocated()) + return PythonObject(); + + PythonObject result = + pfunc(ToSWIGWrapper(breakpoint_sp), ToSWIGWrapper(args_impl), dict); + // FIXME: At this point we should check that the class we found supports all + // the methods that we need. + + if (result.IsAllocated()) { + // Check that __callback__ is defined: + auto callback_func = result.ResolveName("__callback__"); + if (callback_func.IsAllocated()) + return result; + } + return PythonObject(); +} - long long ret_val = unwrapOrSetPythonException(As(result)); +unsigned int lldb_private::LLDBSwigPythonCallBreakpointResolver( + void *implementor, const char *method_name, + lldb_private::SymbolContext *sym_ctx) { + PyErr_Cleaner py_err_cleaner(false); + PythonObject self(PyRefType::Borrowed, static_cast(implementor)); + auto pfunc = self.ResolveName(method_name); - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return 0; - } + if (!pfunc.IsAllocated()) + return 0; - return ret_val; -} + PythonObject result = sym_ctx ? pfunc(ToSWIGWrapper(*sym_ctx)) : pfunc(); -SWIGEXPORT void * -LLDBSwigPythonCreateScriptedStopHook -( - lldb::TargetSP target_sp, - const char *python_class_name, - const char *session_dictionary_name, - lldb_private::StructuredDataImpl *args_impl, - Status &error -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0') { - error.SetErrorString("Empty class name."); - Py_RETURN_NONE; - } - if (!session_dictionary_name) { - error.SetErrorString("No session dictionary"); - Py_RETURN_NONE; - } - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = - PythonModule::MainModule().ResolveName( - session_dictionary_name); - auto pfunc = - PythonObject::ResolveNameWithDictionary( - python_class_name, dict); - - if (!pfunc.IsAllocated()) { - error.SetErrorStringWithFormat("Could not find class: %s.", - python_class_name); - return nullptr; - } + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return 0; + } - lldb::SBTarget *target_val - = new lldb::SBTarget(target_sp); + // The callback will return a bool, but we're need to also return ints + // so we're squirrelling the bool through as an int... And if you return + // nothing, we'll continue. + if (strcmp(method_name, "__callback__") == 0) { + if (result.get() == Py_False) + return 0; + else + return 1; + } - PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_val)); + long long ret_val = unwrapOrSetPythonException(As(result)); - lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); - PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return 0; + } - PythonObject result = pfunc(target_arg, args_arg, dict); + return ret_val; +} - if (result.IsAllocated()) - { - // Check that the handle_stop callback is defined: - auto callback_func = result.ResolveName("handle_stop"); - if (callback_func.IsAllocated()) { - if (auto args_info = callback_func.GetArgInfo()) { - size_t num_args = (*args_info).max_positional_args; - if (num_args != 2) { - error.SetErrorStringWithFormat("Wrong number of args for " +PythonObject lldb_private::LLDBSwigPythonCreateScriptedStopHook( + lldb::TargetSP target_sp, const char *python_class_name, + const char *session_dictionary_name, const StructuredDataImpl &args_impl, + Status &error) { + if (python_class_name == NULL || python_class_name[0] == '\0') { + error.SetErrorString("Empty class name."); + return PythonObject(); + } + if (!session_dictionary_name) { + error.SetErrorString("No session dictionary"); + return PythonObject(); + } + + PyErr_Cleaner py_err_cleaner(true); + + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); + + if (!pfunc.IsAllocated()) { + error.SetErrorStringWithFormat("Could not find class: %s.", + python_class_name); + return PythonObject(); + } + + PythonObject result = + pfunc(ToSWIGWrapper(target_sp), ToSWIGWrapper(args_impl), dict); + + if (result.IsAllocated()) { + // Check that the handle_stop callback is defined: + auto callback_func = result.ResolveName("handle_stop"); + if (callback_func.IsAllocated()) { + if (auto args_info = callback_func.GetArgInfo()) { + size_t num_args = (*args_info).max_positional_args; + if (num_args != 2) { + error.SetErrorStringWithFormat( + "Wrong number of args for " "handle_stop callback, should be 2 (excluding self), got: %zu", num_args); - Py_RETURN_NONE; - } else - return result.release(); - } else { - error.SetErrorString("Couldn't get num arguments for handle_stop " - "callback."); - Py_RETURN_NONE; - } - return result.release(); - } - else { - error.SetErrorStringWithFormat("Class \"%s\" is missing the required " - "handle_stop callback.", - python_class_name); - result.release(); - } + return PythonObject(); + } else + return result; + } else { + error.SetErrorString("Couldn't get num arguments for handle_stop " + "callback."); + return PythonObject(); + } + return result; + } else { + error.SetErrorStringWithFormat("Class \"%s\" is missing the required " + "handle_stop callback.", + python_class_name); } - Py_RETURN_NONE; + } + return PythonObject(); } -SWIGEXPORT bool -LLDBSwigPythonStopHookCallHandleStop -( - void *implementor, - lldb::ExecutionContextRefSP exc_ctx_sp, - lldb::StreamSP stream -) -{ - // handle_stop will return a bool with the meaning "should_stop"... - // If you return nothing we'll assume we are going to stop. - // Also any errors should return true, since we should stop on error. - - PyErr_Cleaner py_err_cleaner(false); - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName("handle_stop"); +bool lldb_private::LLDBSwigPythonStopHookCallHandleStop( + void *implementor, lldb::ExecutionContextRefSP exc_ctx_sp, + lldb::StreamSP stream) { + // handle_stop will return a bool with the meaning "should_stop"... + // If you return nothing we'll assume we are going to stop. + // Also any errors should return true, since we should stop on error. - if (!pfunc.IsAllocated()) - return true; - - PythonObject result; - lldb::SBExecutionContext sb_exc_ctx(exc_ctx_sp); - PythonObject exc_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_exc_ctx)); - lldb::SBStream sb_stream; - PythonObject sb_stream_arg(PyRefType::Owned, - SBTypeToSWIGWrapper(sb_stream)); - result = pfunc(exc_ctx_arg, sb_stream_arg); - - if (PyErr_Occurred()) - { - stream->PutCString("Python error occurred handling stop-hook."); - PyErr_Print(); - PyErr_Clear(); - return true; - } - - // Now add the result to the output stream. SBStream only - // makes an internally help StreamString which I can't interpose, so I - // have to copy it over here. - stream->PutCString(sb_stream.GetData()); - - if (result.get() == Py_False) - return false; - else - return true; -} + PyErr_Cleaner py_err_cleaner(false); + PythonObject self(PyRefType::Borrowed, static_cast(implementor)); + auto pfunc = self.ResolveName("handle_stop"); -// wrapper that calls an optional instance member of an object taking no arguments -static PyObject* -LLDBSwigPython_CallOptionalMember -( - PyObject* implementor, - char* callee_name, - PyObject* ret_if_not_found = Py_None, - bool* was_found = NULL -) -{ - PyErr_Cleaner py_err_cleaner(false); - - PythonObject self(PyRefType::Borrowed, static_cast(implementor)); - auto pfunc = self.ResolveName(callee_name); + if (!pfunc.IsAllocated()) + return true; - if (!pfunc.IsAllocated()) - { - if (was_found) - *was_found = false; - Py_XINCREF(ret_if_not_found); - return ret_if_not_found; - } + auto *sb_stream = new lldb::SBStream(); + PythonObject sb_stream_arg = + ToSWIGWrapper(std::unique_ptr(sb_stream)); + PythonObject result = + pfunc(ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg); - if (was_found) - *was_found = true; + if (PyErr_Occurred()) { + stream->PutCString("Python error occurred handling stop-hook."); + PyErr_Print(); + PyErr_Clear(); + return true; + } + + // Now add the result to the output stream. SBStream only + // makes an internally help StreamString which I can't interpose, so I + // have to copy it over here. + stream->PutCString(sb_stream->GetData()); - PythonObject result = pfunc(); - return result.release(); + if (result.get() == Py_False) + return false; + else + return true; } -SWIGEXPORT size_t -LLDBSwigPython_CalculateNumChildren -( - PyObject *implementor, - uint32_t max -) -{ - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName("num_children"); +// wrapper that calls an optional instance member of an object taking no +// arguments +static PyObject *LLDBSwigPython_CallOptionalMember( + PyObject * implementor, char *callee_name, + PyObject *ret_if_not_found = Py_None, bool *was_found = NULL) { + PyErr_Cleaner py_err_cleaner(false); - if (!pfunc.IsAllocated()) - return 0; + PythonObject self(PyRefType::Borrowed, static_cast(implementor)); + auto pfunc = self.ResolveName(callee_name); - auto arg_info = pfunc.GetArgInfo(); - if (!arg_info) { - llvm::consumeError(arg_info.takeError()); - return 0; - } - - size_t ret_val; - if (arg_info.get().max_positional_args < 1) - ret_val = unwrapOrSetPythonException(As(pfunc.Call())); - else - ret_val = unwrapOrSetPythonException(As(pfunc.Call(PythonInteger(max)))); + if (!pfunc.IsAllocated()) { + if (was_found) + *was_found = false; + Py_XINCREF(ret_if_not_found); + return ret_if_not_found; + } - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - return 0; - } + if (was_found) + *was_found = true; - if (arg_info.get().max_positional_args < 1) - ret_val = std::min(ret_val, static_cast(max)); + PythonObject result = pfunc(); + return result.release(); +} - return ret_val; +size_t lldb_private::LLDBSwigPython_CalculateNumChildren(PyObject * implementor, + uint32_t max) { + PythonObject self(PyRefType::Borrowed, implementor); + auto pfunc = self.ResolveName("num_children"); + + if (!pfunc.IsAllocated()) + return 0; + + auto arg_info = pfunc.GetArgInfo(); + if (!arg_info) { + llvm::consumeError(arg_info.takeError()); + return 0; + } + + size_t ret_val; + if (arg_info.get().max_positional_args < 1) + ret_val = unwrapOrSetPythonException(As(pfunc.Call())); + else + ret_val = unwrapOrSetPythonException( + As(pfunc.Call(PythonInteger(max)))); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return 0; + } + + if (arg_info.get().max_positional_args < 1) + ret_val = std::min(ret_val, static_cast(max)); + + return ret_val; } -SWIGEXPORT PyObject* -LLDBSwigPython_GetChildAtIndex -( - PyObject *implementor, - uint32_t idx -) -{ - PyErr_Cleaner py_err_cleaner(true); +PyObject *lldb_private::LLDBSwigPython_GetChildAtIndex(PyObject * implementor, + uint32_t idx) { + PyErr_Cleaner py_err_cleaner(true); - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName("get_child_at_index"); + PythonObject self(PyRefType::Borrowed, implementor); + auto pfunc = self.ResolveName("get_child_at_index"); - if (!pfunc.IsAllocated()) - return nullptr; + if (!pfunc.IsAllocated()) + return nullptr; - PythonObject result = pfunc(PythonInteger(idx)); + PythonObject result = pfunc(PythonInteger(idx)); - if (!result.IsAllocated()) - return nullptr; + if (!result.IsAllocated()) + return nullptr; - lldb::SBValue* sbvalue_ptr = nullptr; - if (SWIG_ConvertPtr(result.get(), (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) - return nullptr; + lldb::SBValue *sbvalue_ptr = nullptr; + if (SWIG_ConvertPtr(result.get(), (void **)&sbvalue_ptr, + SWIGTYPE_p_lldb__SBValue, 0) == -1) + return nullptr; - if (sbvalue_ptr == nullptr) - return nullptr; + if (sbvalue_ptr == nullptr) + return nullptr; - return result.release(); + return result.release(); } -SWIGEXPORT int -LLDBSwigPython_GetIndexOfChildWithName -( - PyObject *implementor, - const char* child_name -) -{ - PyErr_Cleaner py_err_cleaner(true); +int lldb_private::LLDBSwigPython_GetIndexOfChildWithName( + PyObject * implementor, const char *child_name) { + PyErr_Cleaner py_err_cleaner(true); - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName("get_child_index"); + PythonObject self(PyRefType::Borrowed, implementor); + auto pfunc = self.ResolveName("get_child_index"); - if (!pfunc.IsAllocated()) - return UINT32_MAX; + if (!pfunc.IsAllocated()) + return UINT32_MAX; - llvm::Expected result = pfunc.Call(PythonString(child_name)); + llvm::Expected result = pfunc.Call(PythonString(child_name)); - long long retval = unwrapOrSetPythonException(As(std::move(result))); + long long retval = + unwrapOrSetPythonException(As(std::move(result))); - if (PyErr_Occurred()) { - PyErr_Clear(); // FIXME print this? do something else - return UINT32_MAX; - } + if (PyErr_Occurred()) { + PyErr_Clear(); // FIXME print this? do something else + return UINT32_MAX; + } - if (retval >= 0) - return (uint32_t)retval; + if (retval >= 0) + return (uint32_t)retval; - return UINT32_MAX; + return UINT32_MAX; } -SWIGEXPORT bool -LLDBSwigPython_UpdateSynthProviderInstance -( - PyObject *implementor -) -{ - bool ret_val = false; +bool lldb_private::LLDBSwigPython_UpdateSynthProviderInstance(PyObject * + implementor) { + bool ret_val = false; - static char callee_name[] = "update"; + static char callee_name[] = "update"; - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name); + PyObject *py_return = + LLDBSwigPython_CallOptionalMember(implementor, callee_name); - if (py_return == Py_True) - ret_val = true; + if (py_return == Py_True) + ret_val = true; - Py_XDECREF(py_return); + Py_XDECREF(py_return); - return ret_val; + return ret_val; } -SWIGEXPORT bool -LLDBSwigPython_MightHaveChildrenSynthProviderInstance -( - PyObject *implementor -) -{ - bool ret_val = false; +bool lldb_private::LLDBSwigPython_MightHaveChildrenSynthProviderInstance( + PyObject * implementor) { + bool ret_val = false; - static char callee_name[] = "has_children"; + static char callee_name[] = "has_children"; - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True); + PyObject *py_return = + LLDBSwigPython_CallOptionalMember(implementor, callee_name, Py_True); - if (py_return == Py_True) - ret_val = true; + if (py_return == Py_True) + ret_val = true; - Py_XDECREF(py_return); + Py_XDECREF(py_return); - return ret_val; + return ret_val; } -SWIGEXPORT PyObject* -LLDBSwigPython_GetValueSynthProviderInstance -( - PyObject *implementor -) -{ - PyObject* ret_val = nullptr; +PyObject *lldb_private::LLDBSwigPython_GetValueSynthProviderInstance( + PyObject * implementor) { + PyObject *ret_val = nullptr; - static char callee_name[] = "get_value"; + static char callee_name[] = "get_value"; - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None); + PyObject *py_return = + LLDBSwigPython_CallOptionalMember(implementor, callee_name, Py_None); - if (py_return == Py_None || py_return == nullptr) - ret_val = nullptr; + if (py_return == Py_None || py_return == nullptr) + ret_val = nullptr; - lldb::SBValue* sbvalue_ptr = NULL; + lldb::SBValue *sbvalue_ptr = NULL; - if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) - ret_val = nullptr; - else if (sbvalue_ptr == NULL) - ret_val = nullptr; - else - ret_val = py_return; + if (SWIG_ConvertPtr(py_return, (void **)&sbvalue_ptr, + SWIGTYPE_p_lldb__SBValue, 0) == -1) + ret_val = nullptr; + else if (sbvalue_ptr == NULL) + ret_val = nullptr; + else + ret_val = py_return; - Py_XDECREF(py_return); - return ret_val; + Py_XDECREF(py_return); + return ret_val; } -SWIGEXPORT void* -LLDBSWIGPython_CastPyObjectToSBData -( - PyObject* data -) -{ - lldb::SBData* sb_ptr = nullptr; +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBData(PyObject * data) { + lldb::SBData *sb_ptr = nullptr; - int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0); + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0); - if (valid_cast == -1) - return NULL; + if (valid_cast == -1) + return NULL; - return sb_ptr; + return sb_ptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data) { + lldb::SBError *sb_ptr = nullptr; -SWIGEXPORT void* -LLDBSWIGPython_CastPyObjectToSBError -( - PyObject* data -) -{ - lldb::SBError* sb_ptr = nullptr; - - int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0); + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0); - if (valid_cast == -1) - return NULL; + if (valid_cast == -1) + return NULL; - return sb_ptr; + return sb_ptr; } +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) { + lldb::SBValue *sb_ptr = NULL; -SWIGEXPORT void* -LLDBSWIGPython_CastPyObjectToSBValue -( - PyObject* data -) -{ - lldb::SBValue* sb_ptr = NULL; + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0); - int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0); + if (valid_cast == -1) + return NULL; - if (valid_cast == -1) - return NULL; - - return sb_ptr; + return sb_ptr; } -SWIGEXPORT bool -LLDBSwigPythonCallCommand -( - 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 -) -{ - lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj); - lldb::SBDebugger debugger_sb(debugger); - lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); - - PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); +void *lldb_private::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject * + data) { + lldb::SBMemoryRegionInfo *sb_ptr = NULL; - if (!pfunc.IsAllocated()) - return false; - - // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you - // see comment above for SBCommandReturnObjectReleaser for further details - auto argc = pfunc.GetArgInfo(); - if (!argc) { - llvm::consumeError(argc.takeError()); - return false; - } - PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); - PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb)); - PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb)); + int valid_cast = SWIG_ConvertPtr(data, (void **)&sb_ptr, + SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0); - if (argc.get().max_positional_args < 5u) - pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict); - else - pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict); + if (valid_cast == -1) + return NULL; - return true; + return sb_ptr; } -SWIGEXPORT bool -LLDBSwigPythonCallCommandObject -( - PyObject *implementor, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp -) -{ - lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj); - lldb::SBDebugger debugger_sb(debugger); - lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); - - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName("__call__"); +bool lldb_private::LLDBSwigPythonCallCommand( + 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) { - if (!pfunc.IsAllocated()) - return false; + PyErr_Cleaner py_err_cleaner(true); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you - // see comment above for SBCommandReturnObjectReleaser for further details - PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); - PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb)); - PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb)); + if (!pfunc.IsAllocated()) + return false; - pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg); + auto argc = pfunc.GetArgInfo(); + if (!argc) { + llvm::consumeError(argc.takeError()); + return false; + } + PythonObject debugger_arg = ToSWIGWrapper(std::move(debugger)); + auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj); - return true; + if (argc.get().max_positional_args < 5u) + pfunc(debugger_arg, PythonString(args), cmd_retobj_arg.obj(), dict); + else + pfunc(debugger_arg, PythonString(args), + ToSWIGWrapper(std::move(exe_ctx_ref_sp)), cmd_retobj_arg.obj(), dict); + + return true; } -SWIGEXPORT void* -LLDBSWIGPythonCreateOSPlugin -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP& process_sp -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; +bool lldb_private::LLDBSwigPythonCallCommandObject( + PyObject *implementor, lldb::DebuggerSP debugger, const char *args, + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp) { - PyErr_Cleaner py_err_cleaner(true); + PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); + PythonObject self(PyRefType::Borrowed, implementor); + auto pfunc = self.ResolveName("__call__"); - if (!pfunc.IsAllocated()) - Py_RETURN_NONE; - - // I do not want the SBProcess to be deallocated when going out of scope because python - // has ownership of it and will manage memory for this object by itself - lldb::SBProcess *process_sb = new lldb::SBProcess(process_sp); - PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb)); - if (!process_arg.IsAllocated()) - Py_RETURN_NONE; + if (!pfunc.IsAllocated()) + return false; - auto result = pfunc(process_arg); + auto cmd_retobj_arg = ToSWIGWrapper(cmd_retobj); - if (result.IsAllocated()) - return result.release(); + pfunc(ToSWIGWrapper(std::move(debugger)), PythonString(args), + ToSWIGWrapper(exe_ctx_ref_sp), cmd_retobj_arg.obj()); - Py_RETURN_NONE; + return true; } -SWIGEXPORT void* -LLDBSWIGPython_CreateFrameRecognizer -( - const char *python_class_name, - const char *session_dictionary_name -) -{ - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_class_name, dict); +PythonObject lldb_private::LLDBSWIGPythonCreateOSPlugin( + const char *python_class_name, const char *session_dictionary_name, + const lldb::ProcessSP &process_sp) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); - if (!pfunc.IsAllocated()) - Py_RETURN_NONE; - - auto result = pfunc(); + PyErr_Cleaner py_err_cleaner(true); - if (result.IsAllocated()) - return result.release(); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); - Py_RETURN_NONE; -} + if (!pfunc.IsAllocated()) + return PythonObject(); -SWIGEXPORT PyObject* -LLDBSwigPython_GetRecognizedArguments -( - PyObject *implementor, - const lldb::StackFrameSP& frame_sp -) -{ - static char callee_name[] = "get_recognized_arguments"; - - lldb::SBFrame frame_sb(frame_sp); - PyObject *arg = SBTypeToSWIGWrapper(frame_sb); - - PythonString str(callee_name); - PyObject* result = PyObject_CallMethodObjArgs(implementor, str.get(), arg, - NULL); - return result; + return pfunc(ToSWIGWrapper(process_sp)); } -SWIGEXPORT void* -LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp) -{ - if (!module || !setting) - Py_RETURN_NONE; +PythonObject lldb_private::LLDBSWIGPython_CreateFrameRecognizer( + const char *python_class_name, const char *session_dictionary_name) { + if (python_class_name == NULL || python_class_name[0] == '\0' || + !session_dictionary_name) + return PythonObject(); - PyErr_Cleaner py_err_cleaner(true); - PythonObject py_module(PyRefType::Borrowed, (PyObject *)module); - auto pfunc = py_module.ResolveName("get_dynamic_setting"); + PyErr_Cleaner py_err_cleaner(true); - if (!pfunc.IsAllocated()) - Py_RETURN_NONE; + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_class_name, dict); - lldb::SBTarget target_sb(target_sp); - PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb)); - auto result = pfunc(target_arg, PythonString(setting)); + if (!pfunc.IsAllocated()) + return PythonObject(); - return result.release(); + return pfunc(); } -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordProcess -(const char* python_function_name, -const char* session_dictionary_name, -lldb::ProcessSP& process, -std::string& output) +PyObject *lldb_private::LLDBSwigPython_GetRecognizedArguments( + PyObject * implementor, const lldb::StackFrameSP &frame_sp) { + static char callee_name[] = "get_recognized_arguments"; -{ - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return false; + PythonObject arg = ToSWIGWrapper(frame_sp); - PyErr_Cleaner py_err_cleaner(true); + PythonString str(callee_name); + PyObject *result = + PyObject_CallMethodObjArgs(implementor, str.get(), arg.get(), NULL); + return result; +} - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); +void *lldb_private::LLDBSWIGPython_GetDynamicSetting( + void *module, const char *setting, const lldb::TargetSP &target_sp) { + if (!module || !setting) + Py_RETURN_NONE; - if (!pfunc.IsAllocated()) - return false; + PyErr_Cleaner py_err_cleaner(true); + PythonObject py_module(PyRefType::Borrowed, (PyObject *)module); + auto pfunc = py_module.ResolveName("get_dynamic_setting"); - lldb::SBProcess process_sb(process); - PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb)); - auto result = pfunc(process_arg, dict); + if (!pfunc.IsAllocated()) + Py_RETURN_NONE; - output = result.Str().GetString().str(); + auto result = pfunc(ToSWIGWrapper(target_sp), PythonString(setting)); - return true; + return result.release(); } -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordThread -(const char* python_function_name, -const char* session_dictionary_name, -lldb::ThreadSP& thread, -std::string& output) +bool lldb_private::LLDBSWIGPythonRunScriptKeywordProcess( + const char *python_function_name, const char *session_dictionary_name, + const lldb::ProcessSP &process, std::string &output) { -{ - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return false; + if (python_function_name == NULL || python_function_name[0] == '\0' || + !session_dictionary_name) + return false; - PyErr_Cleaner py_err_cleaner(true); + PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - if (!pfunc.IsAllocated()) - return false; + if (!pfunc.IsAllocated()) + return false; - lldb::SBThread thread_sb(thread); - PythonObject thread_arg(PyRefType::Owned, SBTypeToSWIGWrapper(thread_sb)); - auto result = pfunc(thread_arg, dict); + auto result = pfunc(ToSWIGWrapper(process), dict); - output = result.Str().GetString().str(); + output = result.Str().GetString().str(); - return true; + return true; } -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordTarget -(const char* python_function_name, -const char* session_dictionary_name, -lldb::TargetSP& target, -std::string& output) +std::optional lldb_private::LLDBSWIGPythonRunScriptKeywordThread( + const char *python_function_name, const char *session_dictionary_name, + lldb::ThreadSP thread) { + if (python_function_name == NULL || python_function_name[0] == '\0' || + !session_dictionary_name) + return std::nullopt; -{ - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return false; + PyErr_Cleaner py_err_cleaner(true); - PyErr_Cleaner py_err_cleaner(true); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name,dict); + if (!pfunc.IsAllocated()) + return std::nullopt; - if (!pfunc.IsAllocated()) - return false; - - lldb::SBTarget target_sb(target); - PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb)); - auto result = pfunc(target_arg, dict); - - output = result.Str().GetString().str(); + auto result = pfunc(ToSWIGWrapper(std::move(thread)), dict); - return true; + return result.Str().GetString().str(); } -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordFrame -(const char* python_function_name, -const char* session_dictionary_name, -lldb::StackFrameSP& frame, -std::string& output) +bool lldb_private::LLDBSWIGPythonRunScriptKeywordTarget( + const char *python_function_name, const char *session_dictionary_name, + const lldb::TargetSP &target, std::string &output) { -{ - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return false; + if (python_function_name == NULL || python_function_name[0] == '\0' || + !session_dictionary_name) + return false; - PyErr_Cleaner py_err_cleaner(true); + PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name,dict); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - if (!pfunc.IsAllocated()) - return false; + if (!pfunc.IsAllocated()) + return false; - lldb::SBFrame frame_sb(frame); - PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(frame_sb)); - auto result = pfunc(frame_arg, dict); + auto result = pfunc(ToSWIGWrapper(target), dict); - output = result.Str().GetString().str(); + output = result.Str().GetString().str(); - return true; + return true; } -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordValue -(const char* python_function_name, -const char* session_dictionary_name, -lldb::ValueObjectSP& value, -std::string& output) +std::optional lldb_private::LLDBSWIGPythonRunScriptKeywordFrame( + const char *python_function_name, const char *session_dictionary_name, + lldb::StackFrameSP frame) { + if (python_function_name == NULL || python_function_name[0] == '\0' || + !session_dictionary_name) + return std::nullopt; -{ - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return false; + PyErr_Cleaner py_err_cleaner(true); - PyErr_Cleaner py_err_cleaner(true); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); + if (!pfunc.IsAllocated()) + return std::nullopt; - if (!pfunc.IsAllocated()) - return false; + auto result = pfunc(ToSWIGWrapper(std::move(frame)), dict); - lldb::SBValue value_sb(value); - PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(value_sb)); - auto result = pfunc(value_arg, dict); + return result.Str().GetString().str(); +} - output = result.Str().GetString().str(); +bool lldb_private::LLDBSWIGPythonRunScriptKeywordValue( + const char *python_function_name, const char *session_dictionary_name, + const lldb::ValueObjectSP &value, std::string &output) { - return true; -} + if (python_function_name == NULL || python_function_name[0] == '\0' || + !session_dictionary_name) + return false; -SWIGEXPORT bool -LLDBSwigPythonCallModuleInit -( - const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger -) -{ - std::string python_function_name_string = python_module_name; - python_function_name_string += ".__lldb_init_module"; - const char* python_function_name = python_function_name_string.c_str(); - - PyErr_Cleaner py_err_cleaner(true); - - auto dict = PythonModule::MainModule().ResolveName(session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary(python_function_name, dict); - - // This method is optional and need not exist. So if we don't find it, - // it's actually a success, not a failure. - if (!pfunc.IsAllocated()) - return true; + PyErr_Cleaner py_err_cleaner(true); - lldb::SBDebugger debugger_sb(debugger); - PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); - pfunc(debugger_arg, dict); + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); - return true; -} -%} + if (!pfunc.IsAllocated()) + return false; + auto result = pfunc(ToSWIGWrapper(value), dict); -%runtime %{ -// Forward declaration to be inserted at the start of LLDBWrapPython.h -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBValue.h" + output = result.Str().GetString().str(); -SWIGEXPORT lldb::ValueObjectSP -LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data) -{ - lldb::ValueObjectSP valobj_sp; - if (data) - { - lldb::SBValue* sb_ptr = (lldb::SBValue *)data; - valobj_sp = sb_ptr->GetSP(); - } - return valobj_sp; + return true; } -#ifdef __cplusplus -extern "C" { -#endif +bool lldb_private::LLDBSwigPythonCallModuleInit( + const char *python_module_name, const char *session_dictionary_name, + lldb::DebuggerSP debugger) { + std::string python_function_name_string = python_module_name; + python_function_name_string += ".__lldb_init_module"; + const char *python_function_name = python_function_name_string.c_str(); -void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton); + PyErr_Cleaner py_err_cleaner(true); -#ifdef __cplusplus -} -#endif -%} + auto dict = PythonModule::MainModule().ResolveName( + session_dictionary_name); + auto pfunc = PythonObject::ResolveNameWithDictionary( + python_function_name, dict); -%wrapper %{ + // This method is optional and need not exist. So if we don't find it, + // it's actually a success, not a failure. + if (!pfunc.IsAllocated()) + return true; + pfunc(ToSWIGWrapper(std::move(debugger)), dict); + + return true; +} + +lldb::ValueObjectSP lldb_private::LLDBSWIGPython_GetValueObjectSPFromSBValue( + void *data) { + lldb::ValueObjectSP valobj_sp; + if (data) { + lldb::SBValue *sb_ptr = (lldb::SBValue *)data; + valobj_sp = sb_ptr->GetSP(); + } + return valobj_sp; +} // For the LogOutputCallback functions -void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) { - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyObject *result = PyObject_CallFunction(reinterpret_cast(baton), const_cast("s"), str); - Py_XDECREF(result); - SWIG_PYTHON_THREAD_END_BLOCK; - } +static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, + void *baton) { + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyObject *result = PyObject_CallFunction( + reinterpret_cast(baton), const_cast("s"), str); + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + } } %} diff --git a/gnu/llvm/lldb/bindings/python/python.swig b/gnu/llvm/lldb/bindings/python/python.swig index 9dc4ab87a4b..b1f6c4b9301 100644 --- a/gnu/llvm/lldb/bindings/python/python.swig +++ b/gnu/llvm/lldb/bindings/python/python.swig @@ -84,8 +84,6 @@ void name ## _set(type *t, int index, type val) { import uuid import re import os - -import six %} // Include the version of swig that was used to generate this interface. @@ -121,6 +119,7 @@ def lldb_iter(obj, getsize, getelem): %{ #include "../source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h" +#include "../source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h" #include "../bindings/python/python-swigsafecast.swig" using namespace lldb_private; using namespace lldb_private::python; @@ -132,15 +131,8 @@ using namespace lldb; %include "python-wrapper.swig" %pythoncode%{ -_initialize = True -try: - import lldbconfig - _initialize = lldbconfig.INITIALIZE -except ImportError: - pass debugger_unique_id = 0 -if _initialize: - SBDebugger.Initialize() +SBDebugger.Initialize() debugger = None target = None process = None diff --git a/gnu/llvm/lldb/cmake/caches/Apple-lldb-base.cmake b/gnu/llvm/lldb/cmake/caches/Apple-lldb-base.cmake index 76ab843c4b6..4d4f02bfae9 100644 --- a/gnu/llvm/lldb/cmake/caches/Apple-lldb-base.cmake +++ b/gnu/llvm/lldb/cmake/caches/Apple-lldb-base.cmake @@ -3,7 +3,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "") set(LLVM_TARGETS_TO_BUILD X86;ARM;AArch64 CACHE STRING "") set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") -set(LLVM_ENABLE_MODULES ON CACHE BOOL "") set(LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") set(LIBCXX_ENABLE_STATIC OFF CACHE BOOL "") diff --git a/gnu/llvm/lldb/cmake/modules/AddLLDB.cmake b/gnu/llvm/lldb/cmake/modules/AddLLDB.cmake index 8be214a8509..a5be4afb40f 100644 --- a/gnu/llvm/lldb/cmake/modules/AddLLDB.cmake +++ b/gnu/llvm/lldb/cmake/modules/AddLLDB.cmake @@ -1,3 +1,5 @@ +include(GNUInstallDirs) + function(lldb_tablegen) # Syntax: # lldb_tablegen output-file [tablegen-arg ...] SOURCE source-file @@ -103,7 +105,7 @@ function(add_lldb_library name) # this may result in the wrong install DESTINATION. The FRAMEWORK property # must be set earlier. if(PARAM_FRAMEWORK) - set_target_properties(liblldb PROPERTIES FRAMEWORK ON) + set_target_properties(${name} PROPERTIES FRAMEWORK ON) endif() if(PARAM_SHARED) @@ -113,7 +115,7 @@ function(add_lldb_library name) endif() # RUNTIME is relevant for DLL platforms, FRAMEWORK for macOS install(TARGETS ${name} COMPONENT ${name} - RUNTIME DESTINATION bin + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" LIBRARY DESTINATION ${install_dest} ARCHIVE DESTINATION ${install_dest} FRAMEWORK DESTINATION ${install_dest}) @@ -241,6 +243,16 @@ function(lldb_add_to_buildtree_lldb_framework name subdir) COMMAND ${CMAKE_COMMAND} -E copy $ ${copy_dest} COMMENT "Copy ${name} to ${copy_dest}" ) + + # Create a custom target to remove the copy again from LLDB.framework in the + # build tree. + # Intentionally use remove_directory because the target can be a either a + # file or directory and using remove_directory is harmless for files. + add_custom_target(${name}-cleanup + COMMAND ${CMAKE_COMMAND} -E remove_directory ${copy_dest} + COMMENT "Removing ${name} from LLDB.framework") + add_dependencies(lldb-framework-cleanup + ${name}-cleanup) endfunction() # Add extra install steps for dSYM creation and stripping for the given target. diff --git a/gnu/llvm/lldb/cmake/modules/FindLuaAndSwig.cmake b/gnu/llvm/lldb/cmake/modules/FindLuaAndSwig.cmake index f6251bbd104..763bf0a7bb9 100644 --- a/gnu/llvm/lldb/cmake/modules/FindLuaAndSwig.cmake +++ b/gnu/llvm/lldb/cmake/modules/FindLuaAndSwig.cmake @@ -4,22 +4,21 @@ # # Find Lua and SWIG as a whole. -if(LUA_LIBRARIES AND LUA_INCLUDE_DIR AND SWIG_EXECUTABLE) +if(LUA_LIBRARIES AND LUA_INCLUDE_DIR AND LLDB_ENABLE_SWIG) set(LUAANDSWIG_FOUND TRUE) else() - find_package(SWIG 3.0) - if (SWIG_FOUND) - find_package(Lua 5.3) - if(LUA_FOUND AND SWIG_FOUND) + if (LLDB_ENABLE_SWIG) + find_package(Lua 5.3 EXACT) + if(LUA_FOUND) mark_as_advanced( LUA_LIBRARIES - LUA_INCLUDE_DIR - SWIG_EXECUTABLE) + LUA_INCLUDE_DIR) endif() else() message(STATUS "SWIG 3 or later is required for Lua support in LLDB but could not be found") endif() + include(FindPackageHandleStandardArgs) find_package_handle_standard_args(LuaAndSwig FOUND_VAR @@ -27,5 +26,5 @@ else() REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR - SWIG_EXECUTABLE) + LLDB_ENABLE_SWIG) endif() diff --git a/gnu/llvm/lldb/cmake/modules/FindPythonAndSwig.cmake b/gnu/llvm/lldb/cmake/modules/FindPythonAndSwig.cmake index 3535b548c45..d9305ab31f2 100644 --- a/gnu/llvm/lldb/cmake/modules/FindPythonAndSwig.cmake +++ b/gnu/llvm/lldb/cmake/modules/FindPythonAndSwig.cmake @@ -30,17 +30,15 @@ macro(FindPython3) Python3_LIBRARIES Python3_INCLUDE_DIRS Python3_EXECUTABLE - Python3_RPATH - SWIG_EXECUTABLE) + Python3_RPATH) endif() endmacro() -if(Python3_LIBRARIES AND Python3_INCLUDE_DIRS AND Python3_EXECUTABLE AND SWIG_EXECUTABLE) +if(Python3_LIBRARIES AND Python3_INCLUDE_DIRS AND Python3_EXECUTABLE AND LLDB_ENABLE_SWIG) set(PYTHONANDSWIG_FOUND TRUE) else() - find_package(SWIG 3.0) - if (SWIG_FOUND) - FindPython3() + if (LLDB_ENABLE_SWIG) + FindPython3() else() message(STATUS "SWIG 3 or later is required for Python support in LLDB but could not be found") endif() @@ -64,5 +62,5 @@ else() Python3_LIBRARIES Python3_INCLUDE_DIRS Python3_EXECUTABLE - SWIG_EXECUTABLE) + LLDB_ENABLE_SWIG) endif() diff --git a/gnu/llvm/lldb/cmake/modules/LLDBConfig.cmake b/gnu/llvm/lldb/cmake/modules/LLDBConfig.cmake index b62cd7d2443..ec06ba285f2 100644 --- a/gnu/llvm/lldb/cmake/modules/LLDBConfig.cmake +++ b/gnu/llvm/lldb/cmake/modules/LLDBConfig.cmake @@ -25,7 +25,7 @@ endif() macro(add_optional_dependency variable description package found) cmake_parse_arguments(ARG - "" + "QUIET" "VERSION" "" ${ARGN}) @@ -45,21 +45,26 @@ macro(add_optional_dependency variable description package found) endif() if(${find_package}) - find_package(${package} ${ARG_VERSION} ${maybe_required}) + set(maybe_quiet) + if(ARG_QUIET) + set(maybe_quiet QUIET) + endif() + find_package(${package} ${ARG_VERSION} ${maybe_required} ${maybe_quiet}) set(${variable} "${${found}}") endif() message(STATUS "${description}: ${${variable}}") endmacro() +add_optional_dependency(LLDB_ENABLE_SWIG "Enable SWIG to generate LLDB bindings" SWIG SWIG_FOUND VERSION 3) add_optional_dependency(LLDB_ENABLE_LIBEDIT "Enable editline support in LLDB" LibEdit LibEdit_FOUND) add_optional_dependency(LLDB_ENABLE_CURSES "Enable curses support in LLDB" CursesAndPanel CURSESANDPANEL_FOUND) add_optional_dependency(LLDB_ENABLE_LZMA "Enable LZMA compression support in LLDB" LibLZMA LIBLZMA_FOUND) add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" LuaAndSwig LUAANDSWIG_FOUND) add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in LLDB" PythonAndSwig PYTHONANDSWIG_FOUND) add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" LibXml2 LIBXML2_FOUND VERSION 2.8) +add_optional_dependency(LLDB_ENABLE_FBSDVMCORE "Enable libfbsdvmcore support in LLDB" FBSDVMCore FBSDVMCore_FOUND QUIET) -option(LLDB_USE_SYSTEM_SIX "Use six.py shipped with system and do not install a copy of it" OFF) option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON) option(LLDB_BUILD_FRAMEWORK "Build LLDB.framework (Darwin only)" OFF) option(LLDB_NO_INSTALL_DEFAULT_RPATH "Disable default RPATH settings in binaries" OFF) @@ -67,6 +72,10 @@ option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver for testing (Da option(LLDB_SKIP_STRIP "Whether to skip stripping of binaries when installing lldb." OFF) option(LLDB_SKIP_DSYM "Whether to skip generating a dSYM when installing lldb." OFF) +set(LLDB_GLOBAL_INIT_DIRECTORY "" CACHE STRING + "Path to the global lldbinit directory. Relative paths are resolved relative to the + directory containing the LLDB library.") + if (LLDB_USE_SYSTEM_DEBUGSERVER) # The custom target for the system debugserver has no install target, so we # need to remove it from the LLVM_DISTRIBUTION_COMPONENTS list. @@ -91,6 +100,20 @@ if(LLDB_BUILD_FRAMEWORK) # Essentially, emit the framework's dSYM outside of the framework directory. set(LLDB_DEBUGINFO_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin CACHE STRING "Directory to emit dSYM files stripped from executables and libraries (Darwin Only)") + + # Custom target to remove the targets (binaries, directories) that were + # copied into LLDB.framework in the build tree. + # + # These targets need to be removed before the install phase because otherwise + # because otherwise they may overwrite already installed binaries with the + # wrong RPATH (i.e. build RPATH instead of install RPATH). + # + # This target needs to be created here (rather than in API/CMakeLists.txt) + # because add_lldb_tool creates the custom rules to copy the binaries before + # the framework target exists and that's the only place where this is + # tracked. + add_custom_target(lldb-framework-cleanup + COMMENT "Cleaning up build-tree frameworks in preparation for install") endif() if(APPLE AND CMAKE_GENERATOR STREQUAL Xcode) @@ -159,22 +182,30 @@ else () endif () include_directories("${CMAKE_CURRENT_BINARY_DIR}/../clang/include") +# GCC silently accepts any -Wno- option, but warns about those options +# being unrecognized only if the compilation triggers other warnings to be +# printed. Therefore, check for whether the compiler supports options in the +# form -W, and if supported, add the corresponding -Wno- option. + # Disable GCC warnings -check_cxx_compiler_flag("-Wno-deprecated-declarations" CXX_SUPPORTS_NO_DEPRECATED_DECLARATIONS) -append_if(CXX_SUPPORTS_NO_DEPRECATED_DECLARATIONS "-Wno-deprecated-declarations" CMAKE_CXX_FLAGS) +check_cxx_compiler_flag("-Wdeprecated-declarations" CXX_SUPPORTS_DEPRECATED_DECLARATIONS) +append_if(CXX_SUPPORTS_DEPRECATED_DECLARATIONS "-Wno-deprecated-declarations" CMAKE_CXX_FLAGS) + +check_cxx_compiler_flag("-Wunknown-pragmas" CXX_SUPPORTS_UNKNOWN_PRAGMAS) +append_if(CXX_SUPPORTS_UNKNOWN_PRAGMAS "-Wno-unknown-pragmas" CMAKE_CXX_FLAGS) -check_cxx_compiler_flag("-Wno-unknown-pragmas" CXX_SUPPORTS_NO_UNKNOWN_PRAGMAS) -append_if(CXX_SUPPORTS_NO_UNKNOWN_PRAGMAS "-Wno-unknown-pragmas" CMAKE_CXX_FLAGS) +check_cxx_compiler_flag("-Wstrict-aliasing" CXX_SUPPORTS_STRICT_ALIASING) +append_if(CXX_SUPPORTS_STRICT_ALIASING "-Wno-strict-aliasing" CMAKE_CXX_FLAGS) -check_cxx_compiler_flag("-Wno-strict-aliasing" CXX_SUPPORTS_NO_STRICT_ALIASING) -append_if(CXX_SUPPORTS_NO_STRICT_ALIASING "-Wno-strict-aliasing" CMAKE_CXX_FLAGS) +check_cxx_compiler_flag("-Wstringop-truncation" CXX_SUPPORTS_STRINGOP_TRUNCATION) +append_if(CXX_SUPPORTS_STRINGOP_TRUNCATION "-Wno-stringop-truncation" CMAKE_CXX_FLAGS) # Disable Clang warnings -check_cxx_compiler_flag("-Wno-deprecated-register" CXX_SUPPORTS_NO_DEPRECATED_REGISTER) -append_if(CXX_SUPPORTS_NO_DEPRECATED_REGISTER "-Wno-deprecated-register" CMAKE_CXX_FLAGS) +check_cxx_compiler_flag("-Wdeprecated-register" CXX_SUPPORTS_DEPRECATED_REGISTER) +append_if(CXX_SUPPORTS_DEPRECATED_REGISTER "-Wno-deprecated-register" CMAKE_CXX_FLAGS) -check_cxx_compiler_flag("-Wno-vla-extension" CXX_SUPPORTS_NO_VLA_EXTENSION) -append_if(CXX_SUPPORTS_NO_VLA_EXTENSION "-Wno-vla-extension" CMAKE_CXX_FLAGS) +check_cxx_compiler_flag("-Wvla-extension" CXX_SUPPORTS_VLA_EXTENSION) +append_if(CXX_SUPPORTS_VLA_EXTENSION "-Wno-vla-extension" CMAKE_CXX_FLAGS) # Disable MSVC warnings if( MSVC ) @@ -226,7 +257,7 @@ include_directories(BEFORE if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY include/ COMPONENT lldb-headers - DESTINATION include + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" FILES_MATCHING PATTERN "*.h" PATTERN ".cmake" EXCLUDE @@ -234,7 +265,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ COMPONENT lldb-headers - DESTINATION include + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" FILES_MATCHING PATTERN "*.h" PATTERN ".cmake" EXCLUDE @@ -254,12 +285,12 @@ endif() # directory that LLDB is using for its embedded Clang instance needs to point # to the resource directory of the used Clang installation. if (NOT TARGET clang-resource-headers) - set(LLDB_CLANG_RESOURCE_DIR_NAME "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + set(LLDB_CLANG_RESOURCE_DIR_NAME "${LLVM_VERSION_MAJOR}") # Iterate over the possible places where the external resource directory # could be and pick the first that exists. foreach(CANDIDATE "${Clang_DIR}/../.." "${LLVM_DIR}" "${LLVM_LIBRARY_DIRS}" "${LLVM_BUILD_LIBRARY_DIR}" - "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}") + "${LLVM_LIBRARY_DIR}") # Build the resource directory path by appending 'clang/'. set(CANDIDATE_RESOURCE_DIR "${CANDIDATE}/clang/${LLDB_CLANG_RESOURCE_DIR_NAME}") if (IS_DIRECTORY "${CANDIDATE_RESOURCE_DIR}") diff --git a/gnu/llvm/lldb/cmake/modules/LLDBGenerateConfig.cmake b/gnu/llvm/lldb/cmake/modules/LLDBGenerateConfig.cmake index caeb3969002..5acb7d873db 100644 --- a/gnu/llvm/lldb/cmake/modules/LLDBGenerateConfig.cmake +++ b/gnu/llvm/lldb/cmake/modules/LLDBGenerateConfig.cmake @@ -9,11 +9,9 @@ set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE) check_symbol_exists(ppoll poll.h HAVE_PPOLL) check_symbol_exists(ptsname_r stdlib.h HAVE_PTSNAME_R) set(CMAKE_REQUIRED_DEFINITIONS) -check_symbol_exists(sigaction signal.h HAVE_SIGACTION) check_cxx_symbol_exists(accept4 "sys/socket.h" HAVE_ACCEPT4) check_include_file(termios.h HAVE_TERMIOS_H) -check_include_file("sys/types.h" HAVE_SYS_TYPES_H) check_include_files("sys/types.h;sys/event.h" HAVE_SYS_EVENT_H) check_cxx_symbol_exists(process_vm_readv "sys/uio.h" HAVE_PROCESS_VM_READV) @@ -21,6 +19,8 @@ check_cxx_symbol_exists(__NR_process_vm_readv "sys/syscall.h" HAVE_NR_PROCESS_VM check_library_exists(compression compression_encode_buffer "" HAVE_LIBCOMPRESSION) +set(LLDB_INSTALL_LIBDIR_BASENAME "lib${LLDB_LIBDIR_SUFFIX}") + # These checks exist in LLVM's configuration, so I want to match the LLVM names # so that the check isn't duplicated, but we translate them into the LLDB names # so that I don't have to change all the uses at the moment. diff --git a/gnu/llvm/lldb/cmake/modules/LLDBStandalone.cmake b/gnu/llvm/lldb/cmake/modules/LLDBStandalone.cmake index 98d7848ce99..6dfb459b5b4 100644 --- a/gnu/llvm/lldb/cmake/modules/LLDBStandalone.cmake +++ b/gnu/llvm/lldb/cmake/modules/LLDBStandalone.cmake @@ -1,10 +1,16 @@ +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() + +list(APPEND CMAKE_MODULE_PATH "${LLVM_COMMON_CMAKE_UTILS}/Modules") + option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) find_package(LLVM REQUIRED CONFIG HINTS ${LLVM_DIR} NO_CMAKE_FIND_ROOT_PATH) find_package(Clang REQUIRED CONFIG HINTS ${Clang_DIR} ${LLVM_DIR}/../clang NO_CMAKE_FIND_ROOT_PATH) -# We set LLVM_CMAKE_PATH so that GetSVN.cmake is found correctly when building SVNVersion.inc -set(LLVM_CMAKE_PATH ${LLVM_CMAKE_DIR} CACHE PATH "Path to LLVM CMake modules") +# We set LLVM_CMAKE_DIR so that GetSVN.cmake is found correctly when building SVNVersion.inc +set(LLVM_CMAKE_DIR ${LLVM_CMAKE_DIR} CACHE PATH "Path to LLVM CMake modules") set(LLVM_MAIN_SRC_DIR ${LLVM_BUILD_MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") set(LLVM_MAIN_INCLUDE_DIR ${LLVM_MAIN_INCLUDE_DIR} CACHE PATH "Path to llvm/include") @@ -83,7 +89,26 @@ include(CheckAtomic) include(LLVMDistributionSupport) set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") -set(LLVM_INCLUDE_TESTS ON CACHE INTERNAL "") + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +include_directories( + "${CMAKE_BINARY_DIR}/include" + "${LLVM_INCLUDE_DIRS}" + "${CLANG_INCLUDE_DIRS}") + +if(LLDB_INCLUDE_TESTS) + # Build the gtest library needed for unittests, if we have LLVM sources + # handy. + if (EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest AND NOT TARGET llvm_gtest) + add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest third-party/unittest) + endif() + # LLVMTestingSupport library is needed for Process/gdb-remote. + if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Testing/Support + AND NOT TARGET LLVMTestingSupport) + add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Testing/Support + lib/Testing/Support) + endif() +endif() option(LLVM_USE_FOLDERS "Enable solution folders in Visual Studio. Disable for Express versions." ON) if(LLVM_USE_FOLDERS) @@ -93,14 +118,10 @@ endif() set_target_properties(clang-tablegen-targets PROPERTIES FOLDER "lldb misc") set_target_properties(intrinsics_gen PROPERTIES FOLDER "lldb misc") -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories( - "${CMAKE_BINARY_DIR}/include" - "${LLVM_INCLUDE_DIRS}" - "${CLANG_INCLUDE_DIRS}") +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}) - -set(LLDB_BUILT_STANDALONE 1) diff --git a/gnu/llvm/lldb/docs/conf.py b/gnu/llvm/lldb/docs/conf.py index 0c3cd59fc11..c9e21fa8b8d 100644 --- a/gnu/llvm/lldb/docs/conf.py +++ b/gnu/llvm/lldb/docs/conf.py @@ -12,7 +12,7 @@ # serve to show the default. from __future__ import print_function -import sys, os, re +import sys, os, re, shutil from datetime import date building_man_page = tags.has('builder-man') @@ -61,21 +61,6 @@ source_suffix = { '.rst': 'restructuredtext', } -try: - import recommonmark -except ImportError: - # manpages do not use any .md sources - if not building_man_page: - raise -else: - import sphinx - if sphinx.version_info >= (3, 0): - # This requires 0.5 or later. - extensions.append('recommonmark') - else: - source_parsers = {'.md': 'recommonmark.parser.CommonMarkParser'} - source_suffix['.md'] = 'markdown' - # The encoding of source files. #source_encoding = 'utf-8-sig' @@ -285,20 +270,6 @@ man_pages = [('man/lldb', 'lldb', u'LLDB Documentation', [u'LLVM project'], 1), # If true, show URL addresses after external links. #man_show_urls = False -def process_md(name): - file_subpath = os.path.join(command_guide_subpath, name) - with open(os.path.join(command_guide_path, name)) as f: - title = f.readline().rstrip('\n') - - m = re.match(r'^# (\S+) - (.+)$', title) - if m is None: - print("error: invalid title in %r " - "(expected '# - ')" % file_subpath, - file=sys.stderr) - else: - man_pages.append((file_subpath.replace('.md',''), m.group(1), - m.group(2), man_page_authors, 1)) - # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples @@ -322,8 +293,8 @@ texinfo_documents = [ empty_attr_summary = re.compile(r'\.\. rubric:: Attributes Summary\s*\.\. autosummary::\s*\.\. rubric::') empty_attr_documentation = re.compile(r'\.\. rubric:: Attributes Documentation\s*\.\. rubric::') -def cleanup_source(app, docname, source): - """ Cleans up source files generated by automodapi. """ +def preprocess_source(app, docname, source): + """ Preprocesses source files generated by automodapi. """ # Don't cleanup anything beside automodapi-generated sources. if not automodapi_toctreedirnm in docname: return @@ -349,5 +320,12 @@ def cleanup_source(app, docname, source): # element list). source[0] = processed +def cleanup_source(app, exception): + """ Remove files generated by automodapi in the source tree. """ + if hasattr(app.config, 'automodapi_toctreedirnm'): + api_source_dir = os.path.join(app.srcdir, app.config.automodapi_toctreedirnm) + shutil.rmtree(api_source_dir, ignore_errors=True) + def setup(app): - app.connect('source-read', cleanup_source) + app.connect('source-read', preprocess_source) + app.connect('build-finished', cleanup_source) diff --git a/gnu/llvm/lldb/docs/design/sbapi.rst b/gnu/llvm/lldb/docs/design/sbapi.rst index 676509bbd99..f4a7ca271be 100644 --- a/gnu/llvm/lldb/docs/design/sbapi.rst +++ b/gnu/llvm/lldb/docs/design/sbapi.rst @@ -68,7 +68,7 @@ Like other clang-based tools it requires a compilation database :: - ./bin/lldb-instr /path/to/lldb/source/API/SBDebugger.cpp + $ ./bin/lldb-instr /path/to/lldb/source/API/SBDebugger.cpp The tool will automatically insert ``LLDB_RECORD`` macros inline, however you diff --git a/gnu/llvm/lldb/docs/doxygen.cfg.in b/gnu/llvm/lldb/docs/doxygen.cfg.in index 7750d89fd26..5712779e6b2 100644 --- a/gnu/llvm/lldb/docs/doxygen.cfg.in +++ b/gnu/llvm/lldb/docs/doxygen.cfg.in @@ -916,7 +916,7 @@ HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# it should be included in the main .chm file (NO). GENERATE_CHI = NO diff --git a/gnu/llvm/lldb/docs/index.rst b/gnu/llvm/lldb/docs/index.rst index ffac28a7645..02d44657390 100644 --- a/gnu/llvm/lldb/docs/index.rst +++ b/gnu/llvm/lldb/docs/index.rst @@ -90,7 +90,7 @@ subdirectory: :: - > git clone https://github.com/llvm/llvm-project.git + $ git clone https://github.com/llvm/llvm-project.git Note that LLDB generally builds from top-of-trunk using CMake and Ninja. Additionally it builds: @@ -102,10 +102,10 @@ Additionally it builds: See the :doc:`LLDB Build Page ` for build instructions. -Discussions about LLDB should go to the `lldb-dev -`__ mailing list. Commit +Discussions about LLDB should go to the `LLDB forum +`__. Commit messages are automatically sent to the `lldb-commits -`__ mailing list , and +`__ mailing list, and this is also the preferred mailing list for patch submissions. See the :doc:`Projects page ` if you are looking for some @@ -133,10 +133,13 @@ interesting areas to contribute to lldb. use/variable use/symbolication use/symbols + use/extensions use/python use/python-reference use/remote use/qemu-testing + use/intel_pt + use/ondemand use/troubleshooting use/links @@ -148,6 +151,7 @@ interesting areas to contribute to lldb. resources/contributing resources/build resources/test + resources/fuzzing resources/bots resources/caveats @@ -158,8 +162,6 @@ interesting areas to contribute to lldb. :caption: Design design/overview - design/reproducers - design/structureddataplugins design/sbapi .. toctree:: @@ -179,4 +181,4 @@ interesting areas to contribute to lldb. Source Code Code Reviews - Bug Reports + Bug Reports diff --git a/gnu/llvm/lldb/docs/lldb-gdb-remote.txt b/gnu/llvm/lldb/docs/lldb-gdb-remote.txt index 3eb3dc51c02..4930eb1ccb7 100644 --- a/gnu/llvm/lldb/docs/lldb-gdb-remote.txt +++ b/gnu/llvm/lldb/docs/lldb-gdb-remote.txt @@ -245,7 +245,7 @@ read packet: OK // OUTPUT SCHEMA // { // "name": , -// Tracing technology name, e.g. intel-pt, arm-coresight. +// Tracing technology name, e.g. intel-pt, arm-etm. // "description": , // Description for this technology. // } @@ -280,10 +280,10 @@ read packet: {"name":, "description":}/E;AAAAAAAA // INPUT SCHEMA // { // "type": , -// Tracing technology name, e.g. intel-pt, arm-coresight. +// Tracing technology name, e.g. intel-pt, arm-etm. // // /* thread tracing only */ -// "tids": [], +// "tids"?: [], // Individual threads to trace. // // ... other parameters specific to the provided tracing type @@ -298,16 +298,26 @@ read packet: {"name":, "description":}/E;AAAAAAAA // INTEL-PT // intel-pt supports both "thread tracing" and "process tracing". // -// "Process tracing" is implemented by tracing each thread individually, but -// managed by the same "process trace" instance. -// Each actual thread trace, either from "process tracing" or "thread tracing", -// is stored in an in-memory circular buffer, which keeps the most recent data. +// "Process tracing" is implemented in two different ways. If the +// "perCpuTracing" option is false, then each thread is traced individually +// but managed by the same "process trace" instance. This means that the +// amount of trace buffers used is proportional to the number of running +// threads. This is the recommended option unless the number of threads is +// huge. If "perCpuTracing" is true, then each cpu core is traced invidually +// instead of each thread, which uses a fixed number of trace buffers, but +// might result in less data available for less frequent threads. See +// "perCpuTracing" below for more information. +// +// Each actual intel pt trace buffer, either from "process tracing" or "thread +// tracing", is stored in an in-memory circular buffer, which keeps the most +// recent data. // // Additional params in the input schema: // { -// "threadBufferSize": , -// Trace buffer size per thread in bytes. It must be a power of 2 -// greater than or equal to 4096 (2^12) bytes. +// "iptTraceSize": , +// Size in bytes used by each individual per-thread or per-cpu trace +// buffer. It must be a power of 2 greater than or equal to 4096 (2^12) +// bytes. // // "enableTsc": , // Whether to enable TSC timestamps or not. This is supported on @@ -342,15 +352,36 @@ read packet: {"name":, "description":}/E;AAAAAAAA // 0 if supported. // // /* process tracing only */ +// "perCpuTracing": +// Instead of having an individual trace buffer per thread, this option +// triggers the collection on a per cpu core basis. This effectively +// traces the entire activity on all cores. At decoding time, in order +// to correctly associate a decoded instruction with a thread, the +// context switch trace of each core is needed, as well as a record per +// cpu indicating which thread was running on each core when tracing +// started. These secondary traces are correlated with the intel-pt +// trace by comparing TSC timestamps. +// +// This option forces the capture of TSC timestamps (see "enableTsc"). +// +// Note: This option can't be used simulatenously with any other trace +// sessions because of its system-wide nature. +// +// /* process tracing only */ // "processBufferSizeLimit": , // Maximum total buffer size per process in bytes. -// This limit applies to the sum of the sizes of all trace buffers for -// the current process, excluding the ones started with "thread tracing". -// -// Whenever a thread is attempted to be traced due to "process tracing" -// and the limit would be reached, the process is stopped with a -// "tracing" reason along with a meaningful description, so that the -// user can retrace the process if needed. +// This limit applies to the sum of the sizes of all thread or cpu core +// buffers for the current process, excluding the ones started with +// "thread tracing". +// +// If "perCpuTracing" is false, whenever a thread is attempted to be +// traced due to "process tracing" and the limit would be reached, the +// process is stopped with a "tracing" reason along with a meaningful +// description, so that the user can retrace the process if needed. +// +// If "perCpuTracing" is true, then starting the system-wide trace +// session fails if all the individual per-cpu trace buffers require +// in total more memory that the limit impossed by this parameter. // } // // Notes: @@ -392,7 +423,7 @@ read packet: OK/E;AAAAAAAAA // // { // "type": -// Tracing technology name, e.g. intel-pt, arm-coresight. +// Tracing technology name, e.g. intel-pt, arm-etm. // // /* thread trace stopping only */ // "tids": [] @@ -426,7 +457,7 @@ read packet: OK/E;AAAAAAAAA // INPUT SCHEMA // { // "type": -// Tracing technology name, e.g. intel-pt, arm-coresight. +// Tracing technology name, e.g. intel-pt, arm-etm. // } // // OUTPUT SCHEMA @@ -451,7 +482,24 @@ read packet: OK/E;AAAAAAAAA // "size": , // Size in bytes of this thread data. // }, -// }] +// ], +// "cpus"?: [ +// "id": , +// Identifier for this CPU logical core. +// "binaryData": [ +// { +// "kind": , +// Identifier for some binary data related to this thread to +// fetch with the jLLDBTraceGetBinaryData packet. +// "size": , +// Size in bytes of this cpu core data. +// }, +// ] +// ], +// "warnings"?: [], +// Non-fatal messages useful for troubleshooting. +// +// ... other attributes specific to the given tracing technology // } // // NOTES @@ -460,9 +508,35 @@ read packet: OK/E;AAAAAAAAA // // INTEL PT // +// If per-cpu process tracing is enabled, "tracedThreads" will contain all +// the threads of the process without any trace buffers. Besides that, the +// "cpus" field will also be returned with per cpu core trace buffers. +// A side effect of per-cpu tracing is that all the threads of unrelated +// processes will also be traced, thus polluting the tracing data. +// // Binary data kinds: -// - threadTraceBuffer: trace buffer for a thread. -// - cpuInfo: contents of the /proc/cpuinfo file. +// - iptTrace: trace buffer for a thread or a cpu. +// - perfContextSwitchTrace: context switch trace for a cpu generated by +// perf_event_open. +// - procfsCpuInfo: contents of the /proc/cpuinfo file. +// +// Additional attributes: +// tscPerfZeroConversion: +// +// This field allows converting Intel processor's TSC values to nanoseconds. +// It is available through the Linux perf_event API when cap_user_time and cap_user_time_zero +// are set. +// See the documentation of time_zero in +// https://man7.org/linux/man-pages/man2/perf_event_open.2.html for more information about +// the calculation and the meaning of the values in the schema below. +/// +// Schema for this field: +// +// "tscPerfZeroConversion": { +// "timeMult": , +// "timeShift": , +// "timeZero": , +// } //---------------------------------------------------------------------- send packet: jLLDBTraceGetState:{"type":}] @@ -482,22 +556,14 @@ read packet: {...object}/E;AAAAAAAAA // // { // "type": , -// Tracing technology name, e.g. intel-pt, arm-coresight. +// Tracing technology name, e.g. intel-pt, arm-etm. // "kind": , // Identifier for the data. +// "cpuId": , +// Core id in decimal if the data belongs to a CPU core. // "tid"?: , // Tid in decimal if the data belongs to a thread. -// "offset": , -// Offset of the data in bytes. -// "size": , -// Number of bytes in to read starting from the offset. // } -// -// INTEL PT -// -// Binary data kinds: -// - threadTraceBuffer: trace buffer for a thread. -// - cpuInfo: contents of the /proc/cpuinfo file. //---------------------------------------------------------------------- send packet: jLLDBTraceGetBinaryData:{"type":,"kind":,"tid":,"offset":,"size":}] @@ -1003,6 +1069,15 @@ vendor: is a string that represents the vendor (apple) endian: is one of "little", "big", or "pdp" ptrsize: is a number that represents how big pointers are in bytes +main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows about +main-binary-address: is the load address of the firmware type binary +main-binary-slide: is the slide of the firmware type binary, if address isn't known + +binary-addresses: A comma-separated list of binary load addresses base16. + lldb will parse the binaries in memory to get UUIDs, then + try to find the binaries & debug info by UUID. Intended for + use with a small number of firmware type binaries where the + search for binary/debug info may be expensive. //---------------------------------------------------------------------- // "qShlibInfoAddr" @@ -1206,6 +1281,9 @@ tuples to return are: // is "mt" for AArch64 memory tagging. lldb will // ignore any other flags in this field. + type:[][,]; // memory types that apply to this region, e.g. + // "stack" for stack memory. + error:; // where is // a hex encoded string value that // contains an error string @@ -1848,7 +1926,10 @@ for this region. // The libcompression APIs on darwin systems call this COMPRESSION_LZ4_RAW. // // lzfse -// An Apple proprietary compression algorithm implemented in libcompression. +// Compression algorithm added in macOS 10.11, with open source C reference +// implementation on github. +// https://en.wikipedia.org/wiki/LZFSE +// https://github.com/lzfse/lzfse // // lzma // libcompression implements "LZMA level 6", the default compression for the @@ -2055,3 +2136,38 @@ Example packet: { "port": 5432 }, { "socket_name": "foo" } ] + +//---------------------------------------------------------------------- +// "QSetDetachOnError" +// +// BRIEF +// Sets what the server should do when the communication channel with LLDB +// goes down. Either kill the inferior process (0) or remove breakpoints and +// detach (1). +// +// PRIORITY TO IMPLEMENT +// Low. Only required if the target wants to keep the inferior process alive +// when the communication channel goes down. +//---------------------------------------------------------------------- + +The data in this packet is a single a character, which should be '0' if the +inferior process should be killed, or '1' if the server should remove all +breakpoints and detach from the inferior. + +//---------------------------------------------------------------------- +// "jGetDyldProcessState" +// +// BRIEF +// This packet fetches the process launch state, as reported by libdyld on +// Darwin systems, most importantly to indicate when the system libraries +// have initialized sufficiently to safely call utility functions. +// +// +// LLDB SENDS: jGetDyldProcessState +// STUB REPLIES: {"process_state_value":48,"process_state string":"dyld_process_state_libSystem_initialized"} +// +// PRIORITY TO IMPLEMENT +// Low. This packet is needed to prevent lldb's utility functions for +// scanning the Objective-C class list from running very early in +// process startup. +//---------------------------------------------------------------------- diff --git a/gnu/llvm/lldb/docs/lldb-platform-packets.txt b/gnu/llvm/lldb/docs/lldb-platform-packets.txt index 9a1444afef0..4cf575e5ee8 100644 --- a/gnu/llvm/lldb/docs/lldb-platform-packets.txt +++ b/gnu/llvm/lldb/docs/lldb-platform-packets.txt @@ -94,7 +94,7 @@ incompatible with the flags that gdb specifies. // 2. file path in ascii-hex encoding // // response is F followed by the return value of the mkdir() call, -// base 10 encoded. +// base 16 encoded. //---------------------------------------------------------------------- // qPlatform_shell: @@ -270,7 +270,7 @@ incompatible with the flags that gdb specifies. // send: Fc008 // // response is "F" followed by the file size in base 16. -// "F-1,errno" with the errno if an error occurs. +// "F-1,errno" with the errno if an error occurs, base 16. //---------------------------------------------------------------------- @@ -286,7 +286,7 @@ incompatible with the flags that gdb specifies. // // response is "F" followed by the mode bits in base 16, this 0x1ed would // correspond to 0755 in octal. -// "F-1,errno" with the errno if an error occurs. +// "F-1,errno" with the errno if an error occurs, base 16. //---------------------------------------------------------------------- // vFile:unlink: @@ -300,7 +300,9 @@ incompatible with the flags that gdb specifies. // send: F0 // // Argument is a file path in ascii-hex encoding. -// Response is "F" plus the return value of unlink(), base 10 encoding. +// Response is "F" plus the return value of unlink(), base 16 encoding. +// Return value may optionally be followed by a comma and the base16 +// value of errno if unlink failed. //---------------------------------------------------------------------- // vFile:symlink: @@ -314,7 +316,8 @@ incompatible with the flags that gdb specifies. // send: F0,0 // // Argument file paths are in ascii-hex encoding. -// Response is "F" plus the return value of symlink(), base 10 encoding, twice. +// Response is "F" plus the return value of symlink(), base 16 encoding, +// optionally followed by the value of errno if it failed, also base 16. //---------------------------------------------------------------------- // vFile:chmod: @@ -330,7 +333,7 @@ incompatible with the flags that gdb specifies. // // Arguments are the mode bits to set, base 16, and a file path in // ascii-hex encoding. -// Response is "F" plus the return value of chmod(), base 10 encoding. +// Response is "F" plus the return value of chmod(), base 16 encoding. // // I don't know why there are two packets for the same thing, v. // vFile:chmod:. @@ -369,15 +372,9 @@ incompatible with the flags that gdb specifies. // are the constant values in enum OpenOptions from lldb's File.h // 3. mode bits, base 16 // -// response is F followed by the opened file descriptor in base 10. -// "F-1,errno" with the errno if an error occurs. +// response is F followed by the opened file descriptor in base 16. +// "F-1,errno" with the errno if an error occurs, base 16. // -// COMPATIBILITY -// The gdb-remote serial protocol documentatio defines a vFile:open: -// packet which uses incompatible flag values, e.g. 1 means O_WRONLY -// in gdb's vFile:open:, but it means eOpenOptionRead to lldb's -// implementation. - //---------------------------------------------------------------------- // vFile:close: // @@ -389,8 +386,9 @@ incompatible with the flags that gdb specifies. // receive: vFile:close:7 // send: F0 // -// File descriptor is in base 10. -// "F-1,errno" with the errno if an error occurs. +// File descriptor is in base 16. +// "F-1,errno" with the errno if an error occurs, +// errno is base 16. //---------------------------------------------------------------------- @@ -405,17 +403,12 @@ incompatible with the flags that gdb specifies. // send: F4;a'b\00 // // request packet has the fields: -// 1. file descriptor, base 10 -// 2. number of bytes to be read, base 10 -// 3. offset into file to start from, base 10 +// 1. file descriptor, base 16 +// 2. number of bytes to be read, base 16 +// 3. offset into file to start from, base 16 // -// Response is F, followed by the number of bytes read (base 10), a +// Response is F, followed by the number of bytes read (base 16), a // semicolon, followed by the data in the binary-escaped-data encoding. -// -// COMPATIBILITY -// The gdb-remote serial protocol documentation says that numbers -// in "vFile:" packets should be hexadecimal. Instead lldb uses -// decimal. //---------------------------------------------------------------------- @@ -430,16 +423,11 @@ incompatible with the flags that gdb specifies. // send: F1024 // // request packet has the fields: -// 1. file descriptor, base 10 -// 2. offset into file to start from, base 10 +// 1. file descriptor, base 16 +// 2. offset into file to start from, base 16 // 3. binary-escaped-data to be written // -// Response is F, followed by the number of bytes written (base 10) -// -// COMPATIBILITY -// The gdb-remote serial protocol documentation says that numbers -// in "vFile:" packets should be hexadecimal. Instead lldb uses -// decimal. +// Response is F, followed by the number of bytes written (base 16) diff --git a/gnu/llvm/lldb/docs/python_api_enums.rst b/gnu/llvm/lldb/docs/python_api_enums.rst index 58100b2aa9a..6ae73df68c8 100644 --- a/gnu/llvm/lldb/docs/python_api_enums.rst +++ b/gnu/llvm/lldb/docs/python_api_enums.rst @@ -1019,6 +1019,7 @@ BasicType .. py:data:: eBasicTypeUnsignedWChar .. py:data:: eBasicTypeChar16 .. py:data:: eBasicTypeChar32 +.. py:data:: eBasicTypeChar8 .. py:data:: eBasicTypeShort .. py:data:: eBasicTypeUnsignedShort .. py:data:: eBasicTypeInt diff --git a/gnu/llvm/lldb/docs/resources/bots.rst b/gnu/llvm/lldb/docs/resources/bots.rst index 8a43f53bd25..f2deda52851 100644 --- a/gnu/llvm/lldb/docs/resources/bots.rst +++ b/gnu/llvm/lldb/docs/resources/bots.rst @@ -11,9 +11,8 @@ LLVM Buildbot is the place where volunteers provide build machines. Everyone can * `lldb-x86_64-debian `_ * `lldb-aarch64-ubuntu `_ * `lldb-arm-ubuntu `_ -* `lldb-x86_64-fedora `_ -An overview of all LLDB builders (except Fedora) can be found here: +An overview of all LLDB builders can be found here: `https://lab.llvm.org/buildbot/#/builders?tags=lldb `_ @@ -25,7 +24,6 @@ GreenDragon builds and tests LLDB on macOS. It has a `dedicated tab * `lldb-cmake `_ * `lldb-cmake-matrix `_ -* `lldb-cmake-reproducers `_ * `lldb-cmake-standalone `_ * `lldb-cmake-sanitized `_ diff --git a/gnu/llvm/lldb/docs/resources/build.rst b/gnu/llvm/lldb/docs/resources/build.rst index 6e2afcae0e2..fdbb4d8a005 100644 --- a/gnu/llvm/lldb/docs/resources/build.rst +++ b/gnu/llvm/lldb/docs/resources/build.rst @@ -70,11 +70,11 @@ commands below. :: - > yum install libedit-devel libxml2-devel ncurses-devel python-devel swig - > sudo apt-get install build-essential swig python3-dev libedit-dev libncurses5-dev - > pkg install swig python - > pkgin install swig python36 cmake ninja-build - > brew install swig cmake ninja + $ yum install libedit-devel libxml2-devel ncurses-devel python-devel swig + $ sudo apt-get install build-essential swig python3-dev libedit-dev libncurses5-dev + $ pkg install swig python + $ pkgin install swig python36 cmake ninja-build + $ brew install swig cmake ninja Note that there's an `incompatibility `_ between Python version 3.7 and later @@ -82,45 +82,53 @@ and swig versions older than 4.0.0 which makes builds of LLDB using debug versions of python unusable. This primarily affects Windows, as debug builds of LLDB must use debug python as well. + Windows ******* -* Visual Studio 2017. +* Visual Studio 2019. * The latest Windows SDK. * The Active Template Library (ATL). * `GnuWin32 `_ for CoreUtils and Make. * `Python 3 `_. Make sure to (1) get the x64 variant if that's what you're targetting and (2) install the debug - library if you want to build a debug lldb. + library if you want to build a debug lldb. The standalone installer is the + easiest way to get the debug library. * `Python Tools for Visual Studio - `_. If you plan to debug test - failures or even write new tests at all, PTVS is an indispensable debugging + `_. If you plan to debug test failures + or even write new tests at all, PTVS is an indispensable debugging extension to VS that enables full editing and debugging support for Python (including mixed native/managed debugging). +* `SWIG for Windows `_ The steps outlined here describes how to set up your system and install the required dependencies such that they can be found when needed during the build process. They only need to be performed once. -#. Install Visual Studio with the Windows SDK and ATL components. +#. Install Visual Studio with the "Desktop Development with C++" workload and + the "Python Development" workload. #. Install GnuWin32, making sure ``\bin`` is added to your PATH environment variable. Verify that utilities like ``dirname`` and ``make`` are available from your terminal. #. Install SWIG for Windows, making sure ```` is added to your PATH environment variable. Verify that ``swig`` is available from your terminal. +#. Install Python 3 from the standalone installer and include the debug libraries + in the install, making sure the Python install path is added to your PATH + environment variable. #. Register the Debug Interface Access DLLs with the Registry from a privileged terminal. :: -> regsvr32 "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\DIA SDK\bin\msdia140.dll" -> regsvr32 "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\DIA SDK\bin\amd64\msdia140.dll" +> regsvr32 "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\bin\msdia140.dll" +> regsvr32 "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\bin\amd64\msdia140.dll" Any command prompt from which you build LLDB should have a valid Visual Studio -environment setup. This means you should run ``vcvarsall.bat`` or open an -appropriate Visual Studio Command Prompt corresponding to the version you wish -to use. +environment setup. This means you should open an appropriate `Developer Command +Prompt for VS `_ +corresponding to the version you wish to use or run ``vcvarsall.bat`` or +``VsDevCmd.bat``. macOS ***** @@ -139,7 +147,7 @@ source-tree with git: :: - > git clone https://github.com/llvm/llvm-project.git + $ git clone https://github.com/llvm/llvm-project.git CMake is a cross-platform build-generator tool. CMake does not build the project, it generates the files needed by your build tool. The recommended @@ -155,18 +163,25 @@ to the ``llvm`` directory in the source-tree: :: - > cmake -G Ninja -DLLVM_ENABLE_PROJECTS="clang;lldb" [] path/to/llvm-project/llvm + $ cmake -G Ninja -DLLVM_ENABLE_PROJECTS="clang;lldb" [] path/to/llvm-project/llvm We used the ``LLVM_ENABLE_PROJECTS`` option here to tell the build-system which subprojects to build in addition to LLVM (for more options see :ref:`CommonCMakeOptions` and :ref:`CMakeCaches`). Parts of the LLDB test suite require ``lld``. Add it to the list in order to run all tests. Once CMake is done, -run ninja to perform the actual build. We pass ``lldb`` here as the target, so -it only builds what is necessary to run the lldb driver: +run ninja to perform the actual build. :: - > ninja lldb + $ ninja lldb lldb-server + +If you only want lldb, or are on a platform where lldb-server is not supported, +you can pass just ``lldb``. Ninja will only build what is necessary to run the +lldb driver: + +:: + + $ ninja lldb Standalone builds ***************** @@ -185,10 +200,10 @@ Clang. Then we build the ``ALL`` target with ninja: :: - > cmake -B /path/to/llvm-build -G Ninja \ + $ cmake -B /path/to/llvm-build -G Ninja \ -DLLVM_ENABLE_PROJECTS=clang \ [] /path/to/llvm-project/llvm - > ninja + $ ninja Now run CMake a second time with ``-B`` pointing to a new directory for the main build-tree and the positional argument pointing to the ``lldb`` directory @@ -199,10 +214,13 @@ build directory for Clang, remember to pass its module path via ``Clang_DIR`` :: - > cmake -B /path/to/lldb-build -G Ninja \ + $ cmake -B /path/to/lldb-build -G Ninja \ -DLLVM_DIR=/path/to/llvm-build/lib/cmake/llvm \ [] /path/to/llvm-project/lldb - > ninja lldb + $ ninja lldb lldb-server + +If you do not require or cannot build ``lldb-server`` on your platform, simply +remove it from the Ninja command. .. note:: @@ -225,7 +243,7 @@ ninja: :: - > cmake -G Ninja \ + $ cmake -G Ninja \ -DLLDB_EXPORT_ALL_SYMBOLS=1 \ -DCMAKE_BUILD_TYPE=Debug @@ -237,7 +255,7 @@ suite. :: - > cmake -G Ninja \ + $ cmake -G Ninja \ -DLLDB_TEST_COMPILER= \ @@ -275,7 +293,7 @@ Sample command line: :: - > cmake -G Ninja^ + $ cmake -G Ninja^ -DLLDB_TEST_DEBUG_TEST_CRASHES=1^ -DPYTHON_HOME=C:\Python35^ -DLLDB_TEST_COMPILER=d:\src\llvmbuild\ninja_release\bin\clang.exe^ @@ -292,7 +310,7 @@ project in another directory. :: - > cmake -G "Visual Studio 15 2017 Win64" -Thost=x64 + $ cmake -G "Visual Studio 16 2019" -A x64 -T host=x64 Then you can open the .sln file in Visual Studio, set lldb as the startup project, and use F5 to run it. You need only edit the project settings to set @@ -303,8 +321,8 @@ ninja tree. macOS ^^^^^ -On macOS the LLDB test suite requires libc++. Either add ``libcxx`` to -``LLVM_ENABLE_PROJECTS`` or disable the test suite with +On macOS the LLDB test suite requires libc++. Either add +``LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi"`` or disable the test suite with ``LLDB_INCLUDE_TESTS=OFF``. Further useful options: * ``LLDB_BUILD_FRAMEWORK:BOOL``: Builds the LLDB.framework. @@ -338,14 +356,15 @@ LLVM `_): :: - > git clone https://github.com/llvm/llvm-project + $ git clone https://github.com/llvm/llvm-project - > cmake -B /path/to/lldb-build -G Ninja \ + $ cmake -B /path/to/lldb-build -G Ninja \ -C /path/to/llvm-project/lldb/cmake/caches/Apple-lldb-macOS.cmake \ - -DLLVM_ENABLE_PROJECTS="clang;libcxx;lldb" \ + -DLLVM_ENABLE_PROJECTS="clang;lldb" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ llvm-project/llvm - > DESTDIR=/path/to/lldb-install ninja -C /path/to/lldb-build check-lldb install-distribution + $ DESTDIR=/path/to/lldb-install ninja -C /path/to/lldb-build check-lldb install-distribution .. _CMakeGeneratedXcodeProject: @@ -353,20 +372,21 @@ Build LLDB standalone for development with Xcode: :: - > git clone https://github.com/llvm/llvm-project + $ git clone https://github.com/llvm/llvm-project - > cmake -B /path/to/llvm-build -G Ninja \ + $ cmake -B /path/to/llvm-build -G Ninja \ -C /path/to/llvm-project/lldb/cmake/caches/Apple-lldb-base.cmake \ - -DLLVM_ENABLE_PROJECTS="clang;libcxx" \ + -DLLVM_ENABLE_PROJECTS="clang" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ llvm-project/llvm - > ninja -C /path/to/llvm-build + $ ninja -C /path/to/llvm-build - > cmake -B /path/to/lldb-build \ + $ cmake -B /path/to/lldb-build \ -C /path/to/llvm-project/lldb/cmake/caches/Apple-lldb-Xcode.cmake \ -DLLVM_DIR=/path/to/llvm-build/lib/cmake/llvm \ llvm-project/lldb - > open lldb.xcodeproj - > cmake --build /path/to/lldb-build --target check-lldb + $ open lldb.xcodeproj + $ cmake --build /path/to/lldb-build --target check-lldb .. note:: @@ -381,27 +401,24 @@ Building the Documentation If you wish to build the optional (reference) documentation, additional dependencies are required: -* Sphinx (for the website) +* Sphinx (for the website and the Python API reference) * Graphviz (for the 'dot' tool) * doxygen (if you wish to build the C++ API reference) -* epydoc (if you wish to build the Python API reference) To install the prerequisites for building the documentation (on Debian/Ubuntu) do: :: - > sudo apt-get install doxygen graphviz python3-sphinx - > sudo pip install epydoc + $ sudo apt-get install doxygen graphviz python3-sphinx To build the documentation, configure with ``LLVM_ENABLE_SPHINX=ON`` and build the desired target(s). :: - > ninja docs-lldb-html - > ninja docs-lldb-man - > ninja lldb-cpp-doc - > ninja lldb-python-doc + $ ninja docs-lldb-html + $ ninja docs-lldb-man + $ ninja lldb-cpp-doc Cross-compiling LLDB -------------------- @@ -558,7 +575,7 @@ the -P flag: :: - > export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P` + $ export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P` If you used a different build directory or made a release build, you may need to adjust the above to suit your needs. To test that the lldb Python module is @@ -566,7 +583,7 @@ built correctly and is available to the default Python interpreter, run: :: - > python -c 'import lldb' + $ python -c 'import lldb' Make sure you're using the Python interpreter that matches the Python library diff --git a/gnu/llvm/lldb/docs/resources/contributing.rst b/gnu/llvm/lldb/docs/resources/contributing.rst index 26b13a5b745..b2d4cf0e471 100644 --- a/gnu/llvm/lldb/docs/resources/contributing.rst +++ b/gnu/llvm/lldb/docs/resources/contributing.rst @@ -44,7 +44,7 @@ rules of thumb: missing object files, or otherwise inconsistent debug info, LLVM's error handling types such as `llvm::Expected `_ or - `llvm::Optional + `std::optional `_ should be used. Functions that may fail should return their result using these wrapper types instead of using a bool to indicate success. Returning diff --git a/gnu/llvm/lldb/docs/resources/fuzzing.rst b/gnu/llvm/lldb/docs/resources/fuzzing.rst new file mode 100644 index 00000000000..2b1e7bd1eaa --- /dev/null +++ b/gnu/llvm/lldb/docs/resources/fuzzing.rst @@ -0,0 +1,73 @@ +Fuzzing LLDB +============ + +Overview +-------- + +LLDB has fuzzers that provide automated `fuzz testing `_ for different components of LLDB. The fuzzers are built with `libFuzzer `_ . Currently, there are fuzzers for target creation, LLDB's command interpreter and LLDB's expression evaluator. + +Building the fuzzers +-------------------- + +Building the LLDB fuzzers requires a build configuration that has the address sanitizer and sanitizer coverage enabled. In addition to your regular CMake arguments, you will need these argumets to build the fuzzers: + +:: + + -DLLVM_USE_SANITIZER='Address' \ + -DLLVM_USE_SANITIZE_COVERAGE=On \ + -DCLANG_ENABLE_PROTO_FUZZER=ON + +More information on libFuzzer's sanitizer coverage is available here: ``_ + +If you want to debug LLDB itself when you find a bug using the fuzzers, use the CMake option ``-DCMAKE_BUILD_TYPE='RelWithDebInfo'`` + +To build a fuzzer, run the desired ninja command for the fuzzer(s) you want to build: + +:: + + $ ninja lldb-target-fuzzer + $ ninja lldb-commandinterpreter-fuzzer + $ ninja lldb-expression-fuzzer + +Once built, the binaries for the fuzzers will exist in the ``bin`` directory of your build folder. + +Continuous integration +---------------------- + +Currently, there are plans to integrate the LLDB fuzzers into the `OSS Fuzz `_ project for continuous integration. + +Running the fuzzers +------------------- + +If you want to run the fuzzers locally, you can run the binaries that were generated with ninja from the build directory: + +:: + + $ ./bin/lldb-target-fuzzer + $ ./bin/lldb-commandinterpreter-fuzzer + $ ./bin/lldb-expression-fuzzer + +This will run the fuzzer binaries directly, and you can use the `libFuzzer options `_ to customize how the fuzzers are run. + +Another way to run the fuzzers is to use a ninja target that will both build the fuzzers and then run them immediately after. These custom targets run each fuzzer with command-line arguments that provide better fuzzing for the components being tested. Running the fuzzers this way will also create directories that will store any inputs that caused LLDB to crash, timeout or run out of memory. The directories are created for each fuzzer. + +To run the custom ninja targets, run the command for your desired fuzzer: + +:: + + $ ninja fuzz-lldb-target + $ ninja fuzz-lldb-commandinterpreter + $ ninja fuzz-lldb-expression + +Investigating and reproducing bugs +---------------------------------- + +When the fuzzers find an input that causes LLDB to crash, timeout or run out of memory, the input is saved to a file in the build directory. When running the fuzzer binaries directly this input is stored in a file named ``-``. + +When running the fuzzers using the custom ninja targets shown above, the inputs will be stored in ``fuzzer-artifacts/-artifacts``, which is created in your build directory. The input files will have the name ``--``. + +If you want to reproduce the issue found by a fuzzer once you have gotten the input, you can pass the individual input to the fuzzer binary as a command-line argument: + +:: + + $ ./ diff --git a/gnu/llvm/lldb/docs/resources/test.rst b/gnu/llvm/lldb/docs/resources/test.rst index d2830bc53c1..f91285980f2 100644 --- a/gnu/llvm/lldb/docs/resources/test.rst +++ b/gnu/llvm/lldb/docs/resources/test.rst @@ -173,9 +173,9 @@ but often it's easier to find an existing ``Makefile`` that does something similar to what you want to do. Another thing this enables is having different variants for the same test -case. By default, we run every test for all 3 debug info formats, so once with -DWARF from the object files, once with gmodules and finally with a dSYM on -macOS or split DWARF (DWO) on Linux. But there are many more things we can test +case. By default, we run every test for two debug info formats, once with +DWARF from the object files and another with a dSYM on macOS or split +DWARF (DWO) on Linux. But there are many more things we can test that are orthogonal to the test itself. On GreenDragon we have a matrix bot that runs the test suite under different configurations, with older host compilers and different DWARF versions. @@ -185,10 +185,22 @@ of variants. It's very tempting to add more variants because it's an easy way to increase test coverage. It doesn't scale. It's easy to set up, but increases the runtime of the tests and has a large ongoing cost. -The key take away is that the different variants don't obviate the need for -focused tests. So relying on it to test say DWARF5 is a really bad idea. -Instead you should write tests that check the specific DWARF5 feature, and have -the variant as a nice-to-have. +The test variants are most useful when developing a larger feature (e.g. support +for a new DWARF version). The test suite contains a large number of fairly +generic tests, so running the test suite with the feature enabled is a good way +to gain confidence that you haven't missed an important aspect. However, this +genericness makes them poor regression tests. Because it's not clear what a +specific test covers, a random modification to the test case can make it start +(or stop) testing a completely different part of your feature. And since these +tests tend to look very similar, it's easy for a simple bug to cause hundreds of +tests to fail in the same way. + +For this reason, we recommend using test variants only while developing a new +feature. This can often be done by running the test suite with different +arguments -- without any modifications to the code. You can create a focused +test for any bug found that way. Often, there will be many tests failing, but a +lot of then will have the same root cause. These tests will be easier to debug +and will not put undue burden on all other bots and developers. In conclusion, you'll want to opt for an API test to test the API itself or when you need the expressivity, either for the test case itself or for the @@ -217,7 +229,7 @@ good testing practices. time (e.g., C and C++) there is also usually no process necessary to test the `SBType`-related parts of the API. With those languages it's also possible to test `SBValue` by running expressions with - `SBTarget.EvaluateExpression` or the `expect_expr` testing utility. + `SBTarget.EvaluateExpression` or the ``expect_expr`` testing utility. Functionality that always requires a running process is everything that tests the `SBProcess`, `SBThread`, and `SBFrame` classes. The same is true @@ -303,14 +315,27 @@ A better way to write the test above would be using LLDB's testing function self.expect_expr("2 + 2", result_value="0") **Prefer using specific asserts over the generic assertTrue/assertFalse.**. - The `self.assertTrue`/`self.assertFalse` functions should always be your + The ``self.assertTrue``/``self.assertFalse`` functions should always be your last option as they give non-descriptive error messages. The test class has - several expressive asserts such as `self.assertIn` that automatically + several expressive asserts such as ``self.assertIn`` that automatically generate an explanation how the received values differ from the expected - ones. Check the documentation of Python's `unittest` module to see what - asserts are available. If you can't find a specific assert that fits your - needs and you fall back to a generic assert, make sure you put useful - information into the assert's `msg` argument that helps explain the failure. + ones. Check the documentation of Python's ``unittest`` module to see what + asserts are available. LLDB also has a few custom asserts that are tailored + to our own data types. + ++-----------------------------------------------+-----------------------------------------------------------------+ +| **Assert** | **Description** | ++-----------------------------------------------+-----------------------------------------------------------------+ +| ``assertSuccess`` | Assert that an ``lldb.SBError`` is in the "success" state. | ++-----------------------------------------------+-----------------------------------------------------------------+ +| ``assertState`` | Assert that two states (``lldb.eState*``) are equal. | ++-----------------------------------------------+-----------------------------------------------------------------+ +| ``assertStopReason`` | Assert that two stop reasons (``lldb.eStopReason*``) are equal. | ++-----------------------------------------------+-----------------------------------------------------------------+ + + If you can't find a specific assert that fits your needs and you fall back + to a generic assert, make sure you put useful information into the assert's + ``msg`` argument that helps explain the failure. :: @@ -319,6 +344,71 @@ A better way to write the test above would be using LLDB's testing function # Good. Will print expected_string and the contents of list_of_results. self.assertIn(expected_string, list_of_results) +**Do not use hard-coded line numbers in your test case.** + +Instead, try to tag the line with some distinguishing pattern, and use the function line_number() defined in lldbtest.py which takes +filename and string_to_match as arguments and returns the line number. + +As an example, take a look at test/API/functionalities/breakpoint/breakpoint_conditions/main.c which has these +two lines: + +.. code-block:: c + + return c(val); // Find the line number of c's parent call here. + +and + +.. code-block:: c + + return val + 3; // Find the line number of function "c" here. + +The Python test case TestBreakpointConditions.py uses the comment strings to find the line numbers during setUp(self) and use them +later on to verify that the correct breakpoint is being stopped on and that its parent frame also has the correct line number as +intended through the breakpoint condition. + +**Take advantage of the unittest framework's decorator features.** + +These features can be use to properly mark your test class or method for platform-specific tests, compiler specific, version specific. + +As an example, take a look at test/API/lang/c/forward/TestForwardDeclaration.py which has these lines: + +.. code-block:: python + + @no_debug_info_test + @skipIfDarwin + @skipIf(compiler=no_match("clang")) + @skipIf(compiler_version=["<", "8.0"]) + @expectedFailureAll(oslist=["windows"]) + def test_debug_names(self): + """Test that we are able to find complete types when using DWARF v5 + accelerator tables""" + self.do_test(dict(CFLAGS_EXTRAS="-gdwarf-5 -gpubnames")) + +This tells the test harness that unless we are running "linux" and clang version equal & above 8.0, the test should be skipped. + +**Class-wise cleanup after yourself.** + +TestBase.tearDownClass(cls) provides a mechanism to invoke the platform-specific cleanup after finishing with a test class. A test +class can have more than one test methods, so the tearDownClass(cls) method gets run after all the test methods have been executed by +the test harness. + +The default cleanup action performed by the packages/Python/lldbsuite/test/lldbtest.py module invokes the "make clean" os command. + +If this default cleanup is not enough, individual class can provide an extra cleanup hook with a class method named classCleanup , +for example, in test/API/terminal/TestSTTYBeforeAndAfter.py: + +.. code-block:: python + + @classmethod + def classCleanup(cls): + """Cleanup the test byproducts.""" + cls.RemoveTempFile("child_send1.txt") + + +The 'child_send1.txt' file gets generated during the test run, so it makes sense to explicitly spell out the action in the same +TestSTTYBeforeAndAfter.py file to do the cleanup instead of artificially adding it as part of the default cleanup action which serves to +cleanup those intermediate and a.out files. + Running The Tests ----------------- @@ -509,8 +599,6 @@ line to your ``~/.pdbrc``: alias lldb self.dbg.HandleCommand("%*") -:: - Debugging Test Failures on Windows `````````````````````````````````` @@ -534,7 +622,7 @@ A quick guide to getting started with PTVS is as follows: #. Right click the Project node in Solution Explorer. #. In the General tab, Make sure Python 3.5 Debug is the selected Interpreter. #. In Debug/Search Paths, enter the path to your ninja/lib/site-packages directory. - #. In Debug/Environment Variables, enter ``VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\``. + #. In Debug/Environment Variables, enter ``VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\``. #. If you want to enabled mixed mode debugging, check Enable native code debugging (this slows down debugging, so enable it only on an as-needed basis.) #. Set the command line for the test suite to run. #. Right click the project in solution explorer and choose the Debug tab. diff --git a/gnu/llvm/lldb/docs/testsuite/a-detailed-walkthrough.txt b/gnu/llvm/lldb/docs/testsuite/a-detailed-walkthrough.txt index fff5a40d1da..57c9dbce3d0 100644 --- a/gnu/llvm/lldb/docs/testsuite/a-detailed-walkthrough.txt +++ b/gnu/llvm/lldb/docs/testsuite/a-detailed-walkthrough.txt @@ -73,7 +73,7 @@ Now let's look inside the test method: def test_set_output_path(self): """Test that setting target.process.output-path for the launched process works.""" - self.buildDefault() + self.build() exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) @@ -96,49 +96,12 @@ Now let's look inside the test method: self.expect(output, exe=False, startstr = "This message should go to standard out.") -The self.buildDefault() statement is used to build a default binary for this -test instance. For this particular test case, since we don't really care what -debugging format is used, we instruct the build subsystem to build the default -binary for us. The base class TestBase has defined three instance methods: - - def buildDefault(self, architecture=None, compiler=None, dictionary=None): - """Platform specific way to build the default binaries.""" - module = __import__(sys.platform) - if not module.buildDefault(self, architecture, compiler, dictionary): - raise Exception("Don't know how to build default binary") - - def buildDsym(self, architecture=None, compiler=None, dictionary=None): - """Platform specific way to build binaries with dsym info.""" - module = __import__(sys.platform) - if not module.buildDsym(self, architecture, compiler, dictionary): - raise Exception("Don't know how to build binary with dsym") - - def buildDwarf(self, architecture=None, compiler=None, dictionary=None): - """Platform specific way to build binaries with dwarf maps.""" - module = __import__(sys.platform) - if not module.buildDwarf(self, architecture, compiler, dictionary): - raise Exception("Don't know how to build binary with dwarf") - -And the test/plugins/darwin.py provides the implementation for all three build -methods using the makefile mechanism. We envision that linux plugin can use a -similar approach to accomplish the task of building the binaries. - -macOS provides an additional way to manipulate archived DWARF debug symbol -files and produces dSYM files. The buildDsym() instance method is used by the -test method to build the binary with dsym info. For an example of this, -see test/array_types/TestArrayTypes.py: - - @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") - def test_with_dsym_and_run_command(self): - """Test 'frame variable var_name' on some variables with array types.""" - self.buildDsym() - self.array_types() - -This method is decorated with a skipUnless decorator so that it will only gets -included into the test suite if the platform it is running on is 'darwin', a.k.a. -macOS. - -Type 'man dsymutil' for more details. +The self.build() statement is used to build a binary for this +test instance. This will build the binary for the current debug info format. If +we wanted to avoid running the test for every supported debug info format we +could annotate it with @no_debug_info_test. The test would then only be run for +the default format. The logic for building a test binary resides in the builder +modules (packages/Python/lldbsuite/test/builders/builder.py) After the binary is built, it is time to specify the file to be used as the main executable by lldb: @@ -147,19 +110,9 @@ executable by lldb: exe = self.getBuildArtifact("a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) -This is where the attribute assignment: - -class SettingsCommandTestCase(TestBase): - - mydir = "settings" - -which happens right after the SettingsCommandTestCase class declaration comes -into place. It specifies the relative directory to the top level 'test' so that -the test harness can change its working directory in order to find the -executable as well as the source code files. The runCmd() method is defined in -the TestBase base class (within test/lldbtest.py) and its purpose is to pass the -specified command to the lldb command interpreter. It's like you're typing the -command within an interactive lldb session. +The runCmd() method is defined in the TestBase base class and its purpose is to +pass the specified command to the lldb command interpreter. It's like you're +typing the command within an interactive lldb session. The CURRENT_EXECUTABLE_SET is an assert message defined in the lldbtest module so that it can be reused from other test modules. diff --git a/gnu/llvm/lldb/docs/use/extensions.rst b/gnu/llvm/lldb/docs/use/extensions.rst new file mode 100644 index 00000000000..3c73326dfa2 --- /dev/null +++ b/gnu/llvm/lldb/docs/use/extensions.rst @@ -0,0 +1,138 @@ +DWARF Extensions supported by LLDB +================================== + +LLDB supports some DWARF extensions produced by Clang. + +Clang ``-gmodules`` debug info +------------------------------ + +On Darwin platforms, including Apple macOS and iOS, Clang can emit +DWARF debug info for types found in `Clang +modules `_ more efficiently. + +From an on-disk storage perspective, Clang modules are precompiled +header files that contain serialized Clang ASTs of all the +declarations found in a Clang module. In traditional DWARF debug info, +two object files that were built from sources that imported the same +header file will both contain DWARF debug type info for types in that +header file. This can lead to a lot of redundant `debug +info `_. + +When Clang compiles a Clang module or precompiled header with the +``-gmodules`` option, the precompiled header (``.pch``) or module +(``.pcm``) files become object file containers (on Darwin: Mach-O) +that hold a ``__clang_ast`` section with the serialized Clang AST and +various DWARF sections containing debug info for the type declarations +found in the header or module. + +This allows Clang to omit these type definitions from the object +(``.o``) files and replace them with forward declarations to save +space. Type declarations in a Clang module are nested inside one +``DW_TAG_module``, or -- in the case of submodules -- multiple levels +of ``DW_TAG_module``. If a DWARF DIE needs to reference a type DIE +from another module, Clang emits a forward declaration of the +referenced DIE into a ``DW_TAG_module`` inside the same compile unit. + +When a consumer sees a forward declaration that is nested inside a +``DW_TAG_module``, it knows that it can find the full type declaration +in an external ``.pcm`` or ``.pch`` file. To facilitate locating these +external dependencies, Clang emits skeleton CUs into each object file +that references external modules. Clang uses the same mechanism that +is used to locate external ``.dwo`` files on ELF-based platforms. The +``DW_AT_GNU_dwo_name`` contains the absolute path to the ``.pcm`` +file, and the ``DW_AT_GNU_dwo_id`` is a hash of the contents that is +repeated in the ``DW_TAG_compile_unit`` of the ``.pcm`` file. + +For example: + +M.h + +:: + + struct A { + int x; + }; + + +M.pcm + +:: + + DW_TAG_compile_unit + DW_AT_GNU_dwo_id (0xabcdef) + DW_TAG_module + DW_AT_name "M" + DW_TAG_structure + DW_AT_name "A" + DW_TAG_member + DW_AT_name "x" + +A.c + +:: + + A a; + +A.o + +:: + + DW_TAG_compile_unit + DW_TAG_module + DW_AT_name "M" + DW_TAG_structure + DW_AT_name "A" + DW_AT_declaration (true) + DW_TAG_variable + DW_AT_name "a" + DW_AT_type (local ref to fwd decl "A") + + DW_TAG_compile_unit + DW_AT_GNU_dwo_id (0xabcdef) + DW_AT_GNU_dwo_name ("M.pcm") + +The debug info inside a ``.pcm`` file may recursively reference +further external types that are defined in other ``.pcm`` files. Clang +generates external references (and debug info inside the modules) for +the following types: + +C: + +- ``struct`` +- ``union`` +- ``enum`` +- ``typedef`` + +Objective-C: + +- all the C types listed above +- ``@interface`` + +C++: + +- all the C types listed above +- ``namespace`` +- any explicit ``extern template`` specializations + +LLDB supports this DWARF extension only when debugging from ``.o`` +files. The ``dsymutil`` debug info linker also understands this format +and will resolve all module type references to point straight to the +underlying defining declaration. Because of this a ``.dSYM`` bundle +will never contain any ``-gmodules``-style references. + +Apple SDK information +--------------------- + +Clang and the Swift compiler emit information about the Xcode SDK that +was used to build a translation unit into the ``DW_TAG_compile_unit``. +The ``DW_AT_LLVM_sysroot`` attribute points to the SDK root +(equivalent to Clang's ``-isysroot`` option). The ``DW_AT_APPLE_sdk`` +attribute contains the name of the SDK, for example ``MacOSX.sdk``. + +Objective-C runtime +------------------- + +Clang emits the Objective-C runtime version into the +``DW_TAG_compile_unit`` using the +``DW_AT_APPLE_major_runtime_version`` attribute. The value 2 stands +for Objective-C 2.0. diff --git a/gnu/llvm/lldb/docs/use/intel_pt.rst b/gnu/llvm/lldb/docs/use/intel_pt.rst new file mode 100644 index 00000000000..694615c83fb --- /dev/null +++ b/gnu/llvm/lldb/docs/use/intel_pt.rst @@ -0,0 +1,252 @@ +Tracing with Intel Processor Trace +================================== + +.. contents:: + :local: + +Intel PT is a technology available in modern Intel CPUs that allows efficient +tracing of all the instructions executed by a process. +LLDB can collect traces and dump them using its symbolication stack. +You can read more here +https://easyperf.net/blog/2019/08/23/Intel-Processor-Trace. + +Prerequisites +------------- + +Confirm that your CPU supports Intel PT +(see https://www.intel.com/content/www/us/en/support/articles/000056730/processors.html) +and that your operating system is Linux. + +Check for the existence of this particular file on your Linux system + +:: + + $ cat /sys/bus/event_source/devices/intel_pt/type + +The output should be a number. Otherwise, try upgrading your kernel. + + +Build Instructions +------------------ + +Clone and build the low level Intel PT +decoder library [LibIPT library](https://github.com/intel/libipt). +:: + + $ git clone git@github.com:intel/libipt.git + $ mkdir libipt-build + $ cmake -S libipt -B libipt-build + $ cd libipt-build + $ make + +This will generate a few files in the ``/lib`` +and ``/libipt/include`` directories. + +Configure and build LLDB with Intel PT support + +:: + + $ cmake \ + -DLLDB_BUILD_INTEL_PT=ON \ + -DLIBIPT_INCLUDE_PATH="/libipt/include" \ + -DLIBIPT_LIBRARY_PATH="/lib" \ + ... other common configuration parameters + +:: + + $ cd && ninja lldb lldb-server # if using Ninja + + +How to Use +---------- + +When you are debugging a process, you can turn on intel-pt tracing, +which will “record” all the instructions that the process will execute. +After turning it on, you can continue debugging, and at any breakpoint, +you can inspect the instruction list. + +For example: + +:: + + lldb + > b main + > run + > process trace start # start tracing on all threads, including future ones + # keep debugging until you hit a breakpoint + + > thread trace dump instructions + # this should output something like + + thread #2: tid = 2861133, total instructions = 5305673 + libc.so.6`__GI___libc_read + 45 at read.c:25:1 + [4962255] 0x00007fffeb64c63d subq $0x10, %rsp + [4962256] 0x00007fffeb64c641 movq %rdi, -0x18(%rbp) + libc.so.6`__GI___libc_read + 53 [inlined] __libc_read at read.c:26:10 + [4962257] 0x00007fffeb64c645 callq 0x7fffeb66b640 ; __libc_enable_asynccancel + libc.so.6`__libc_enable_asynccancel + [4962258] 0x00007fffeb66b640 movl %fs:0x308, %eax + libc.so.6`__libc_enable_asynccancel + 8 + [4962259] 0x00007fffeb66b648 movl %eax, %r11d + + # you can keep pressing ENTER to see more and more instructions + +The number between brackets is the instruction index, +and by default the current thread will be picked. + +Configuring the trace size +-------------------------- + +The CPU stores the instruction list in a compressed format in a ring buffer, +which keeps the latest information. +By default, LLDB uses a buffer of 4KB per thread, +but you can change it by running. +The size must be a power of 2 and at least 4KB. + +:: + + thread trace start all -s + +For reference, a 1MB trace buffer can easily store around 5M instructions. + +Printing more instructions +-------------------------- + +If you want to dump more instructions at a time, you can run + +:: + + thread trace dump instructions -c + +Printing the instructions of another thread +------------------------------------------- + +By default the current thread will be picked when dumping instructions, +but you can do + +:: + + thread trace dump instructions <#thread index> + #e.g. + thread trace dump instructions 8 + +to select another thread. + +Crash Analysis +-------------- + +What if you are debugging + tracing a process that crashes? +Then you can just do + +:: + + thread trace dump instructions + +To inspect how it crashed! There's nothing special that you need to do. +For example + +:: + + * thread #1, name = 'a.out', stop reason = signal SIGFPE: integer divide by zero + frame #0: 0x00000000004009f1 a.out`main at main.cpp:8:14 + 6 int x; + 7 cin >> x; + -> 8 cout << 12 / x << endl; + 9 return 0; + 10 } + (lldb) thread trace dump instructions -c 5 + thread #1: tid = 604302, total instructions = 8388 + libstdc++.so.6`std::istream::operator>>(int&) + 181 + [8383] 0x00007ffff7b41665 popq %rbp + [8384] 0x00007ffff7b41666 retq + a.out`main + 66 at main.cpp:8:14 + [8385] 0x00000000004009e8 movl -0x4(%rbp), %ecx + [8386] 0x00000000004009eb movl $0xc, %eax + [8387] 0x00000000004009f0 cltd + +.. note:: + At this moment, we are not including the failed instruction in the trace, + but in the future we might do it for readability. + + +Offline Trace Analysis +---------------------- + +It's also possible to record a trace using a custom Intel PT collector +and decode + symbolicate the trace using LLDB. +For that, the command trace load is useful. +In order to use trace load, you need to first create a JSON file with +the definition of the trace session. +For example + +:: + + { + "type": "intel-pt", + "cpuInfo": { + "vendor": "GenuineIntel", + "family": 6, + "model": 79, + "stepping": 1 + }, + "processes": [ + { + "pid": 815455, + "triple": "x86_64-*-linux", + "threads": [ + { + "tid": 815455, + "iptTrace": "trace.file" # raw thread-specific trace from the AUX buffer + } + ], + "modules": [ # this are all the shared libraries + the main executable + { + "file": "a.out", # optional if it's the same as systemPath + "systemPath": "a.out", + "loadAddress": 4194304, + }, + { + "file": "libfoo.so", + "systemPath": "/usr/lib/libfoo.so", + "loadAddress": "0x00007ffff7bd9000", + }, + { + "systemPath": "libbar.so", + "loadAddress": "0x00007ffff79d7000", + } + ] + } + ] + } + +You can see the full schema by typing + +:: + + trace schema intel-pt + +The JSON file mainly contains all the shared libraries that +were part of the traced process, along with their memory load address. +If the analysis is done on the same computer where the traces were obtained, +it's enough to use the “systemPath” field. +If the analysis is done on a different machines, these files need to be +copied over and the “file” field should point to the +location of the file relative to the JSON file. +Once you have the JSON file and the module files in place, you can simple run + +:: + + lldb + > trace load /path/to/json + > thread trace dump instructions + +Then it's like in the live session case + +References +---------- + +- Original RFC document_ for this feature. +- Some details about how Meta is using Intel Processor Trace can be found in this blog_ post. + +.. _document: https://docs.google.com/document/d/1cOVTGp1sL_HBXjP9eB7qjVtDNr5xnuZvUUtv43G5eVI +.. _blog: https://engineering.fb.com/2021/04/27/developer-tools/reverse-debugging/ diff --git a/gnu/llvm/lldb/docs/use/links.rst b/gnu/llvm/lldb/docs/use/links.rst new file mode 100644 index 00000000000..595a78c8db8 --- /dev/null +++ b/gnu/llvm/lldb/docs/use/links.rst @@ -0,0 +1,82 @@ +Links +===== + +This page contains links to external resources on how to use LLDB. Being +listed on this page is not an endorsement. + +Blog Posts +---------- + +`Dancing in the Debugger — A Waltz with LLDB (2014)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A high level overview of LLDB with a focus on debugging Objective-C +code. + +Videos +------ + +`LLDB: Beyond “po” (2019)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LLDB is a powerful tool for exploring and debugging your app at runtime. +Discover the various ways to display values in your app, how to format +custom data types, and how to extend LLDB using your own Python 3 +scripts. + +`Advanced Debugging with Xcode and LLDB (2018)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Discover advanced techniques, and tips and tricks for enhancing your +Xcode debugging workflows. Learn how to take advantage of LLDB and +custom breakpoints for more powerful debugging. Get the most out of +Xcode’s view debugging tools to solve UI issues in your app more +efficiently. + +`Debugging with LLDB (2012)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LLDB is the next-generation debugger for macOS and iOS. Get an +introduction to using LLDB via the console interface and within Xcode’s +graphical debugger. The team that created LLDB will demonstrate the +latest features and improvements, helping you track down bugs more +efficiently than ever before. + +`Migrating from GDB to LLDB (2011)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LLDB is the next-generation debugger for macOS and iOS. Discover why +you’ll want to start using LLDB in your own development, get expert tips +from the team that created LLDB, and see how it will help you track down +bugs more efficiently than ever before. + +Books +----- + +`Advanced Apple Debugging & Reverse Engineering (2018)`_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A book about using LLDB on Apple platforms. + +Extensions +---------- + +`facebook/chisel`_ +~~~~~~~~~~~~~~~~~~ + +Chisel is a collection of LLDB commands to assist in the debugging of +iOS apps. + +`DerekSelander/LLDB`_ +~~~~~~~~~~~~~~~~~~~~~ + +A collection of LLDB aliases/regexes and Python scripts. + +.. _Dancing in the Debugger — A Waltz with LLDB (2014): https://www.objc.io/issues/19-debugging/lldb-debugging/ +.. _`LLDB: Beyond “po” (2019)`: https://developer.apple.com/videos/play/wwdc2019/429/ +.. _Advanced Debugging with Xcode and LLDB (2018): https://developer.apple.com/videos/play/wwdc2018/412/ +.. _Debugging with LLDB (2012): https://developer.apple.com/videos/play/wwdc2012/415/ +.. _Migrating from GDB to LLDB (2011): https://developer.apple.com/videos/play/wwdc2011/321/ +.. _Advanced Apple Debugging & Reverse Engineering (2018): https://www.raywenderlich.com/books/advanced-apple-debugging-reverse-engineering/ +.. _facebook/chisel: https://github.com/facebook/chisel +.. _DerekSelander/LLDB: https://github.com/DerekSelander/LLDB diff --git a/gnu/llvm/lldb/docs/use/map.rst b/gnu/llvm/lldb/docs/use/map.rst index 569649a0b2a..b11d583a227 100644 --- a/gnu/llvm/lldb/docs/use/map.rst +++ b/gnu/llvm/lldb/docs/use/map.rst @@ -1,7 +1,7 @@ GDB to LLDB command map ======================= -Below is a table of GDB commands with the LLDB counterparts. The built in +Below is a table of GDB commands with their LLDB counterparts. The built in GDB-compatibility aliases in LLDB are also listed. The full lldb command names are often long, but any unique short form can be used. Instead of "**breakpoint set**", "**br se**" is also acceptable. @@ -58,7 +58,7 @@ Execution Commands - Launch a process for with arguments a.out 1 2 3 without having to supply the args every time. + Launch process a.out with arguments 1 2 3 without having to supply the args every time. @@ -124,9 +124,7 @@ Execution Commands - Launch a process with arguments in existing terminal - /dev/ttys006 (macOS only). - + Launch a process with arguments <args> in existing terminal /dev/ttys006 (macOS only). @@ -205,7 +203,7 @@ Execution Commands - Attach to a process with process ID 123. + Attach to the process with process ID 123. @@ -219,7 +217,7 @@ Execution Commands - Attach to a process named "a.out". + Attach to the process named "a.out". @@ -410,6 +408,22 @@ Execution Commands + + Show the current frame and source line. + + + + (gdb) frame + + + (lldb) frame select +
+ (lldb) f +
+ (lldb) process status + + + @@ -427,7 +441,7 @@ Breakpoint Commands - Set a breakpoint at all functions named main. + Set a breakpoint at all functions named main. @@ -443,7 +457,7 @@ Breakpoint Commands - Set a breakpoint in file test.c at line 12. + Set a breakpoint in file test.c at line 12. @@ -459,7 +473,7 @@ Breakpoint Commands - Set a breakpoint at all C++ methods whose basename is main. + Set a breakpoint at all C++ methods whose basename is main. @@ -476,7 +490,7 @@ Breakpoint Commands - Set a breakpoint at and object C function: -[NSString stringWithFormat:]. + Set a breakpoint at an Objective-C function -[NSString stringWithFormat:]. @@ -492,7 +506,7 @@ Breakpoint Commands - Set a breakpoint at all Objective-C methods whose selector is count. + Set a breakpoint at all Objective-C methods whose selector is count. @@ -525,7 +539,7 @@ Breakpoint Commands - Ensure that breakpoints by file and line work for #included .c/.cpp/.m files. + Ensure that breakpoints by file and line work for #include .c/.cpp/.m files. @@ -561,7 +575,7 @@ Breakpoint Commands - Set a conditional breakpoint + Set a conditional breakpoint. @@ -885,7 +899,7 @@ Examining Variables - Display the variables "argc" and "argv" only when you stop in the function named main. + Display the variables "argc" and "argv" only when you stop in the function named main. @@ -899,7 +913,7 @@ Examining Variables - Display the variable "*this" only when you stop in c class named MyClass. + Display the variable "*this" only when you stop in c class named MyClass. @@ -1027,7 +1041,7 @@ Evaluating Expressions - Calling a function so you can stop at a breakpoint in the function. + Call a function so you can stop at a breakpoint in it. @@ -1043,7 +1057,7 @@ Evaluating Expressions - Calling a function that crashes, and stopping when the function crashes. + Call a function that crashes, then stop when it does. @@ -1276,7 +1290,7 @@ Examining Thread State - Show the general purpose registers for the current thread formatted as signed decimal. LLDB tries to use the same format characters as printf(3) when possible. Type "help format" to see the full list of format specifiers. + Show the general purpose registers for the current thread formatted as signed decimal. LLDB tries to use the same format characters as printf(3) when possible. Type "help format" to see the full list of format specifiers. @@ -1348,7 +1362,7 @@ Examining Thread State - Read memory from address 0xbffff3c0 and show 4 hex uint32_t values. + Read memory from address 0xbffff3c0 and show 4 hex uint32_t values. @@ -1393,7 +1407,7 @@ Examining Thread State - Read 512 bytes of memory from address 0xbffff3c0 and save results to a local file as text. + Read 512 bytes of memory from address 0xbffff3c0 and save the results to a local file as text. @@ -1500,7 +1514,7 @@ Examining Thread State - Disassemble any functions named main. + Disassemble any functions named main. @@ -1671,7 +1685,7 @@ Executable and Shared Library Query Commands - Look up information for an address in a.out only. + Look up information for an address in a.out only. @@ -1715,7 +1729,7 @@ Executable and Shared Library Query Commands - Dump all sections in the a.out module. + Dump all sections in the a.out module. @@ -1739,7 +1753,7 @@ Executable and Shared Library Query Commands - Dump all symbols in a.out and liba.so. + Dump all symbols in a.out and liba.so. @@ -1794,7 +1808,7 @@ Miscellaneous - Remap source file pathnames for the debug session. If your source files are no longer located in the same location as when the program was built --- maybe the program was built on a different computer --- you need to tell the debugger how to find the sources at their local file path instead of the build system's file path. + Remap source file pathnames for the debug session. If your source files are no longer located in the same location as when the program was built (for example, if the program was built on a different computer) you need to tell the debugger how to find the sources at their local file path instead of the build system's file path. diff --git a/gnu/llvm/lldb/docs/use/ondemand.rst b/gnu/llvm/lldb/docs/use/ondemand.rst new file mode 100644 index 00000000000..e5aaee8889d --- /dev/null +++ b/gnu/llvm/lldb/docs/use/ondemand.rst @@ -0,0 +1,158 @@ +On Demand Symbols +================= + +On demand symbols can be enabled in LLDB for projects that generate debug info +for more than what is required by a normal debug session. Some build systems +enable debug information for all binaries and can end up producing many +gigabytes of debug information. This amount of debug information can greatly +increase debug session load times and can slow developer productivity when the +debug information isn't indexed. It can also cause expression evaluation to +be slow when types from all of the binaries have full debug info as each module +is queried for very common types, or global name lookups fail due to a mistyped +expression. + +.. contents:: + :local: + +When should I consider enabling this feature? +--------------------------------------------- + +Anyone that has a build system that produces debug information for many +binaries that are not all required when you want to focus on debugging a few of +the produced binaries. Some build systems enable debug info as a project wide +switch and the build system files that control how things are built are not +easy to modify to produce debug info for only a small subset of the files being +linked. If your debug session startup times are slow because of too much debug +info, this feature might help you be more productive during daily use. + +How do I enable on demand symbols? +---------------------------------- + +This feature is enabled using a LLDB setting: + + +:: + + (lldb) settings set symbols.load-on-demand true + +Users can also put this command into their ~/.lldbinit file so it is always +enabled. + +How does this feature work? +--------------------------- + +This feature works by selectively enabling debug information for modules that +the user focuses on. It is designed to be enabled and work without the user +having to set any other settings and will try and determine when to enable +debug info access from the modules automatically. All modules with debug info +start off with their debug information turned off for expensive name and type +lookups. The debug information for line tables are always left enabled to allow +users to reliably set breakpoints by file and line. As the user debugs their +target, some simple things can cause module to get its debug information +enabled (called hydration): +- Setting a file and line breakpoint +- Any PC from any stack frame that maps to a module +- Setting a breakpoint by function name +- Finding a global variable by name + +Since most users set breakpoints by file and line, this is an easy way for +people to inform the debugger that they want focus on this module. Breakpoints +by file and line are always enabled when on demand symbols is being used. Line +tables in debug information are cheap to parse and breakpoints will be able to +be set in any module that has debug info. Setting breakpoints by file and line +acts as one of the primary ways to enable debug info for a module as it is +the most common way to stop your program at interesting areas of your code. + +Once the user hits a breakpoint, or stops the program for any other reason, +like a crash, assertion or signal, the debugger will calculate the stack frames +for one or more threads. Any stack frames whose PC value is contained within +one of a module's sections will have its debug information enabled. This allows +us to enable debug information for the areas of code that the user is stopped +in and will allow only the important subset of modules to have their debug +information enabled. + +On demand symbol loading tries to avoid indexing the names within the debug +information and makes a few tradeoffs to allow name matching of functions and +globals without having to always index all of the debug information. +Setting breakpoints by function name can work, but we try to avoid using +debug information by relying on the symbol tables from a module. Debug +information name indexing is one of the most expensive operations that we are +trying to avoid with the on demand symbol loading so this is one of the main +tradeoffs of this feature. When setting a breakpoint by function name, if the +symbol table contains a match, the debug inforamation will be enabled for that +module and the query will be completed using the debug information. This does +mean that setting breakpoints on inline function names can fail for modules +that have debug info, but no matches in the symbol table since inlined +functions don't exist in symbol tables. When using on demand symbol loading it +is encouraged to not strip the symbol tables of local symbols as this will +allow users to set breakpoints on all concrete functions reliably. Stripped +symbol tables have their local symbols removed from the symbol table which +means that static functions and non exported function will not appear in the +symbol tables. This can cause breakpoint setting by function name to fail when +previously it wouldn't fail. + +Global variable lookups rely on the same methodology as breakpoint setting by +function name: we use the symbol tables to find a match first if debug +information isn't enabled for a module. If we find a match in the symbol table +for a global variable lookup, we will enable debug inforamation and complete +the query using the debug information. It is encouraged to not strip your +symbol tables with this features as static variables and other non exported +globals will not appear in the symbol table and can lead to matches not being +found. + +What other things might fail? +----------------------------- + +The on demand symbol loading feature tries to limit expensive name lookups +within debug inforamtion. As such, some lookups by name might fail when they +wouldn't when this feature is not eabled: +- Setting breakpoints by function name for inlined functions +- Type lookups when the expression parser requests types by name +- Global variable lookups by name when the name of the variable is stripped + +Setting breakpoints by function name can fail for inline function because this +information is only contained in the debug information. No symbols are created +for inlined functions unless there is a concrete copy of the inlined function +in that same module. As a result, we might not end up stopping at all inlined +functions when requested with this feature enabled. Setting file and line +breakpoints are a good way still use on demand symbol loading effectively +and still being able to stop at inline function invocations. + +The expression parser often tries to lookup types by name when the user types +an expression. These are some of the most costly parts of expression evaluation +as the user can type something like "iterator" as part of their expression and +this can result in matches from all STL types in all modules. These kinds of +global type lookup queries can cause thousands of results to be found if debug +information is enabled. The way that most debug information is created these +days has the type information inlined into each module. Typically each module +will contain full type definitions in the debug info for any types that are +used in code. This means that when you type an expression when stopped, you +have debug information for all of the variables, arguments and global variables +in your current stack frame and we should be able to find type that are +important by using only the modules that have their debug information enabled. + +The expression parser can also be asked to display global variables and they +can be looked up by name. For this feature to work reliably with on demand +symbol loading enabled, just don't strip your symbol tables and the expression +parser should have no problem finding your variables. Most global variables +that are exported will still be in your symbol table if it is stripped, but +static variables and non exported globals will not be. + +Can I troubleshoot issues when I believe this feature is impeding my debugging? +------------------------------------------------------------------------------- + +Logging has been added that can be enabled to help notify our engineers when +something is not producing results when this feature is enabled. This logging +can be enabled during a debug session and can be sent to the LLDB engineers +to help troubleshoot these situation. To enable logging, type the following +command: + +:: + + (lldb) log enable -f /tmp/ondemand.txt lldb on-demand + +When the logging is enabled, we get full visibility into each query that would +have produced results if this feature were not enabled and will allow us to +troublshoot issues. Enabling this logging before an expression, setting a +breakpoint by name, or doing a type lookup can help us see the patterns that +cause failures and will help us improve this feature. diff --git a/gnu/llvm/lldb/docs/use/python-reference.rst b/gnu/llvm/lldb/docs/use/python-reference.rst index 33e1de11e80..2020853cfd2 100644 --- a/gnu/llvm/lldb/docs/use/python-reference.rst +++ b/gnu/llvm/lldb/docs/use/python-reference.rst @@ -356,7 +356,7 @@ The custom Resolver is provided as a Python class with the following methods: | | | symbol name, you could write a generic symbol name based Resolver, and then allow the user to pass | | | | in the particular symbol in the extra_args | +--------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``__callback__`` | ``sym_ctx``:`lldb.SBSymbolContext` | This is the Resolver callback. | +| ``__callback__`` | ``sym_ctx``:`lldb.SBSymbolContext` | This is the Resolver callback. | | | | The ``sym_ctx`` argument will be filled with the current stage | | | | of the search. | | | | | @@ -378,7 +378,7 @@ The custom Resolver is provided as a Python class with the following methods: | | | So you would want to return `lldb.eSearchDepthModule`. This method is optional. If not provided the search | | | | will be done at Module depth. | +--------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------+ -| ``get_short_help` | ``None`` | This is an optional method. If provided, the returned string will be printed at the beginning of | +| ``get_short_help`` | ``None`` | This is an optional method. If provided, the returned string will be printed at the beginning of | | | | the description for this breakpoint. | +--------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------+ @@ -442,7 +442,7 @@ And for a MUCH fuller discussion of the whole state machine, see: https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Target/ThreadPlan.h If you are reading those comments it is useful to know that scripted thread -plans are set to be "MasterPlans", and not "OkayToDiscard". +plans are set to be "ControllingPlans", and not "OkayToDiscard". To implement a scripted step, you define a python class that has the following methods: @@ -584,26 +584,33 @@ the form: where debugger and internal_dict are as above, that function will get run when the module is loaded allowing you to add whatever commands you want into the current debugger. Note that this function will only be run when using the LLDB -command command script import, it will not get run if anyone imports your -module from another module. If you want to always run code when your module is -loaded from LLDB or when loaded via an import statement in python code you can -test the lldb.debugger object, since you imported the module at the top of the -python ls.py module. This test must be in code that isn't contained inside of -any function or class, just like the standard test for __main__ like all python -modules usually do. Sample code would look like: +command ``command script import``, it will not get run if anyone imports your +module from another module. + +The standard test for ``__main__``, like many python modules do, is useful for +creating scripts that can be run from the command line. However, for command +line scripts, the debugger instance must be created manually. Sample code would +look like: :: if __name__ == '__main__': + # Initialize the debugger before making any API calls. + lldb.SBDebugger.Initialize() # Create a new debugger instance in your module if your module # can be run from the command line. When we run a script from # the command line, we won't have any debugger object in # lldb.debugger, so we can just create it if it will be needed - lldb.debugger = lldb.SBDebugger.Create() - elif lldb.debugger: - # Module is being run inside the LLDB interpreter - lldb.debugger.HandleCommand('command script add -f ls.ls ls') - print 'The "ls" python command has been installed and is ready for use.' + debugger = lldb.SBDebugger.Create() + + # Next, do whatever work this module should do when run as a command. + # ... + + # Finally, dispose of the debugger you just made. + lldb.SBDebugger.Destroy(debugger) + # Terminate the debug session + lldb.SBDebugger.Terminate() + Now we can create a module called ls.py in the file ~/ls.py that will implement a function that can be used by LLDB's python command code: @@ -629,7 +636,7 @@ Now we can load the module into LLDB and use it :: - % lldb + $ lldb (lldb) command script import ~/ls.py The "ls" python command has been installed and is ready for use. (lldb) ls -l /tmp/ @@ -637,6 +644,51 @@ Now we can load the module into LLDB and use it -rw-r--r--@ 1 someuser wheel 6148 Jan 19 17:27 .DS_Store -rw------- 1 someuser wheel 7331 Jan 19 15:37 crash.log +You can also make "container" commands to organize the commands you are adding to +lldb. Most of the lldb built-in commands structure themselves this way, and using +a tree structure has the benefit of leaving the one-word command space free for user +aliases. It can also make it easier to find commands if you are adding more than +a few of them. Here's a trivial example of adding two "utility" commands into a +"my-utilities" container: + +:: + + #!/usr/bin/env python + + import lldb + + def first_utility(debugger, command, result, internal_dict): + print("I am the first utility") + + def second_utility(debugger, command, result, internal_dict): + print("I am the second utility") + + # And the initialization code to add your commands + def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand('command container add -h "A container for my utilities" my-utilities') + debugger.HandleCommand('command script add -f my_utilities.first_utility -h "My first utility" my-utilities first') + debugger.HandleCommand('command script add -f my_utilities.second_utility -h "My second utility" my-utilities second') + print('The "my-utilities" python command has been installed and its subcommands are ready for use.') + +Then your new commands are available under the my-utilities node: + +:: + + (lldb) help my-utilities + A container for my utilities + + Syntax: my-utilities + + The following subcommands are supported: + + first -- My first utility Expects 'raw' input (see 'help raw-input'.) + second -- My second utility Expects 'raw' input (see 'help raw-input'.) + + For more help on any particular subcommand, type 'help '. + (lldb) my-utilities first + I am the first utility + + A more interesting template has been created in the source repository that can help you to create lldb command quickly: @@ -673,7 +725,7 @@ that goal: Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> def pofoo_funct(debugger, command, result, internal_dict): ... cmd = "po [ModifyString(" + command + ") capitalizedString]" - ... lldb.debugger.HandleCommand(cmd) + ... debugger.HandleCommand(cmd) ... >>> ^D (lldb) command script add pofoo -f pofoo_funct @@ -706,7 +758,7 @@ For sh and bash: :: - % export PYTHONPATH=`lldb -P` + $ export PYTHONPATH=`lldb -P` Alternately, you can append the LLDB Python directory to the sys.path list directly in your Python code before importing the lldb module. @@ -808,7 +860,8 @@ functions 'read', 'write' and 'close' follows: def get_recognized_arguments(self, frame): if frame.name in ["read", "write", "close"]: fd = frame.EvaluateExpression("$arg1").unsigned - value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd) + target = frame.thread.process.target + value = target.CreateValueFromExpression("fd", "(int)%d" % fd) return [value] return [] diff --git a/gnu/llvm/lldb/docs/use/python.rst b/gnu/llvm/lldb/docs/use/python.rst index efbe0d732c1..32f1f3595f6 100644 --- a/gnu/llvm/lldb/docs/use/python.rst +++ b/gnu/llvm/lldb/docs/use/python.rst @@ -36,7 +36,7 @@ the input text file: :: - % ./dictionary Romeo-and-Juliet.txt + $ ./dictionary Romeo-and-Juliet.txt Dictionary loaded. Enter search word: love Yes! @@ -45,7 +45,7 @@ the input text file: Enter search word: Romeo No! Enter search word: ^D - % + $ Using Depth First Search ------------------------ @@ -184,7 +184,7 @@ you would do something like this: :: - % lldb + $ lldb (lldb) process attach -n "dictionary" Architecture set to: x86_64. Process 521 stopped @@ -500,12 +500,11 @@ tree_utils.py - Example Python functions using LLDB's API, including DFS """ # ===-- tree_utils.py ---------------------------------------*- Python -*-===// # - # The LLVM Compiler Infrastructure + # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + # See https://llvm.org/LICENSE.txt for license information. + # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # - # This file is distributed under the University of Illinois Open Source - # License. See LICENSE.TXT for details. - # - # ===---------------------------------------------------------------------===// + # ===----------------------------------------------------------------------===// tree_utils.py - A set of functions for examining binary search trees, based on the example search tree defined in @@ -623,12 +622,11 @@ dictionary.c - Sample dictionary program, with bug //===-- dictionary.c ---------------------------------------------*- C -*-===// // - // The LLVM Compiler Infrastructure - // - // This file is distributed under the University of Illinois Open Source - // License. See LICENSE.TXT for details. + // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + // See https://llvm.org/LICENSE.txt for license information. + // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // - //===---------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// #include #include #include diff --git a/gnu/llvm/lldb/docs/use/remote.rst b/gnu/llvm/lldb/docs/use/remote.rst index 0eb43fbb82f..1649becea78 100644 --- a/gnu/llvm/lldb/docs/use/remote.rst +++ b/gnu/llvm/lldb/docs/use/remote.rst @@ -135,6 +135,11 @@ application needs additional files, you can transfer them using the platform commands: get-file, put-file, mkdir, etc. The environment can be prepared further using the platform shell command. +When using the "remote-android" platform, the client LLDB forwards two ports, one +for connecting to the platform, and another for connecting to the gdbserver. +The client ports are configurable through the environment variables +ANDROID_PLATFORM_LOCAL_PORT and ANDROID_PLATFORM_LOCAL_GDB_PORT, respectively. + Launching a locally built process on the remote machine ------------------------------------------------------- diff --git a/gnu/llvm/lldb/docs/use/symbolication.rst b/gnu/llvm/lldb/docs/use/symbolication.rst index 2c10a886d60..f7ecf381e0a 100644 --- a/gnu/llvm/lldb/docs/use/symbolication.rst +++ b/gnu/llvm/lldb/docs/use/symbolication.rst @@ -402,5 +402,5 @@ the crash log. -i, --interactive parse all crash logs and enter interactive mode -The source for the "symbolication" and "crashlog" modules are available in SVN. +The source for the "symbolication" and "crashlog" modules are available in git. diff --git a/gnu/llvm/lldb/docs/use/troubleshooting.rst b/gnu/llvm/lldb/docs/use/troubleshooting.rst index bf858a5870a..3e4fea99551 100644 --- a/gnu/llvm/lldb/docs/use/troubleshooting.rst +++ b/gnu/llvm/lldb/docs/use/troubleshooting.rst @@ -18,7 +18,7 @@ files: :: - % cat foo.c + $ cat foo.c #include "bar.c" #include "baz.c" ... @@ -32,7 +32,7 @@ search for inlined breakpoint locations by adding the following line to your :: - % echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit + $ echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit This tells LLDB to always look in all compile units and search for breakpoint locations by file and line even if the implementation file doesn't match. diff --git a/gnu/llvm/lldb/docs/use/tutorial.rst b/gnu/llvm/lldb/docs/use/tutorial.rst index 3c552a341e0..d4da0bae5aa 100644 --- a/gnu/llvm/lldb/docs/use/tutorial.rst +++ b/gnu/llvm/lldb/docs/use/tutorial.rst @@ -509,9 +509,9 @@ running anything you type will go to the STDIN of the inferior process. To interrupt your inferior program, type CTRL+C. If you attach to a process, or launch a process with the "--no-stdin" option, -the command interpreter is always available to enter commands. This might be a -little disconcerting to gdb users when always have an (lldb) prompt. This -allows you to set a breakpoint, etc without having to explicitly interrupt the +the command interpreter is always available to enter commands. It might be a +little disconcerting to gdb users to always have an (lldb) prompt. This allows +you to set a breakpoint, etc without having to explicitly interrupt the program you are debugging: :: diff --git a/gnu/llvm/lldb/docs/use/variable.rst b/gnu/llvm/lldb/docs/use/variable.rst index b3e4de588d5..1afe7c28b6b 100644 --- a/gnu/llvm/lldb/docs/use/variable.rst +++ b/gnu/llvm/lldb/docs/use/variable.rst @@ -7,7 +7,7 @@ Variable Formatting LLDB has a data formatters subsystem that allows users to define custom display options for their variables. -Usually, when you type frame variable or run some expression LLDB will +Usually, when you type ``frame variable`` or run some expression LLDB will automatically choose the way to display your results on a per-type basis, as in the following example: @@ -17,7 +17,11 @@ the following example: (uint8_t) x = 'a' (intptr_t) y = 124752287 -However, in certain cases, you may want to associate a different style to the display for certain datatypes. To do so, you need to give hints to the debugger +Note: ``frame variable`` without additional arguments prints the list of +variables of the current frame. + +However, in certain cases, you may want to associate a different style to the +display for certain datatypes. To do so, you need to give hints to the debugger as to how variables should be displayed. The LLDB type command allows you to do just that. @@ -29,6 +33,63 @@ Using it you can change your visualization to look like this: (uint8_t) x = chr='a' dec=65 hex=0x41 (intptr_t) y = 0x76f919f +In addition, some data structures can encode their data in a way that is not +easily readable to the user, in which case a data formatter can be used to +show the data in a human readable way. For example, without a formatter, +printing a ``std::deque`` with the elements ``{2, 3, 4, 5, 6}`` would +result in something like: + +:: + + (lldb) frame variable a_deque + (std::deque >) $0 = { + std::_Deque_base > = { + _M_impl = { + _M_map = 0x000000000062ceb0 + _M_map_size = 8 + _M_start = { + _M_cur = 0x000000000062cf00 + _M_first = 0x000000000062cf00 + _M_last = 0x000000000062d2f4 + _M_node = 0x000000000062cec8 + } + _M_finish = { + _M_cur = 0x000000000062d300 + _M_first = 0x000000000062d300 + _M_last = 0x000000000062d6f4 + _M_node = 0x000000000062ced0 + } + } + } + } + +which is very hard to make sense of. + +Note: ``frame variable `` prints out the variable ```` in the current +frame. + +On the other hand, a proper formatter is able to produce the following output: + +:: + + (lldb) frame variable a_deque + (std::deque >) $0 = size=5 { + [0] = 2 + [1] = 3 + [2] = 4 + [3] = 5 + [4] = 6 + } + +which is what the user would expect from a good debugger. + +Note: you can also use ``v `` instead of ``frame variable ``. + +It's worth mentioning that the ``size=5`` string is produced by a summary +provider and the list of children is produced by a synthetic child provider. +More information about these providers is available later in this document. + + There are several features related to data visualization: formats, summaries, filters, synthetic children. @@ -426,9 +487,7 @@ themselves, but which carry a special meaning when used in this context: | ``%>`` | Print the expression path for this item | +------------+--------------------------------------------------------------------------+ -Starting with SVN r228207, you can also specify -``${script.var:pythonFuncName}``. Previously, back to r220821, this was -specified with a different syntax: ``${var.script:pythonFuncName}``. +Since lldb 3.7.0, you can also specify ``${script.var:pythonFuncName}``. It is expected that the function name you use specifies a function whose signature is the same as a Python summary function. The return string from the @@ -715,7 +774,7 @@ something you have to deal with on your own. ``options`` Python summary formatters can optionally define this third argument, which is an object of type ``lldb.SBTypeSummaryOptions``, allowing for a few customizations of the result. The decision to -adopt or not this third argument - and the meaning of options +adopt or not this third argument - and the meaning of options thereof - is up to the individual formatter's writer. Other than interactively typing a Python script there are two other ways for @@ -749,6 +808,7 @@ of type names. This would let you rephrase the above example for arrays of type Simple [3] as: :: + (lldb) type summary add --summary-string "${var[].x}" -x "Simple \[[0-9]+\]" (lldb) frame variable (Simple [3]) sarray = [1,4,7] @@ -871,29 +931,36 @@ be implemented by the Python class): this call should return a new LLDB SBValue object representing the child at the index given as argument def update(self): this call should be used to update the internal state of this Python object whenever the state of the variables in LLDB changes.[1] + Also, this method is invoked before any other method in the interface. def has_children(self): this call should return True if this object might have children, and False if this object can be guaranteed not to have children.[2] def get_value(self): this call can return an SBValue to be presented as the value of the synthetic value under consideration.[3] -[1] This method is optional. Also, it may optionally choose to return a value -(starting with SVN rev153061/LLDB-134). If it returns a value, and that value -is True, LLDB will be allowed to cache the children and the children count it -previously obtained, and will not return to the provider class to ask. If -nothing, None, or anything other than True is returned, LLDB will discard the -cached information and ask. Regardless, whenever necessary LLDB will call -update. - -[2] This method is optional (starting with SVN rev166495/LLDB-175). While -implementing it in terms of num_children is acceptable, implementors are -encouraged to look for optimized coding alternatives whenever reasonable. - -[3] This method is optional (starting with SVN revision 219330). The `SBValue` -you return here will most likely be a numeric type (int, float, ...) as its -value bytes will be used as-if they were the value of the root `SBValue` proper. -As a shortcut for this, you can inherit from lldb.SBSyntheticValueProvider, and -just define get_value as other methods are defaulted in the superclass as -returning default no-children responses. +As a warning, exceptions that are thrown by python formatters are caught +silently by LLDB and should be handled appropriately by the formatter itself. +Being more specific, in case of exceptions, LLDB might assume that the given +object has no children or it might skip printing some children, as they are +printed one by one. + +[1] This method is optional. Also, a boolean value must be returned (since lldb +3.1.0). If ``False`` is returned, then whenever the process reaches a new stop, +this method will be invoked again to generate an updated list of the children +for a given variable. Otherwise, if ``True`` is returned, then the value is +cached and this method won't be called again, effectively freezing the state of +the value in subsequent stops. Beware that returning ``True`` incorrectly could +show misleading information to the user. + +[2] This method is optional (since lldb 3.2.0). While implementing it in terms +of num_children is acceptable, implementors are encouraged to look for +optimized coding alternatives whenever reasonable. + +[3] This method is optional (since lldb 3.5.2). The `SBValue` you return here +will most likely be a numeric type (int, float, ...) as its value bytes will be +used as-if they were the value of the root `SBValue` proper. As a shortcut for +this, you can inherit from lldb.SBSyntheticValueProvider, and just define +get_value as other methods are defaulted in the superclass as returning default +no-children responses. If a synthetic child provider supplies a special child named ``$$dereference$$`` then it will be used when evaluating ``operator *`` and @@ -972,6 +1039,24 @@ instead of the real ones. For instance, (int) [3] = 1234 } +It's important to mention that LLDB invokes the synthetic child provider before +invoking the summary string provider, which allows the latter to have access to +the actual displayable children. This applies to both inlined summary strings +and python-based summary providers. + + +As a warning, when programmatically accessing the children or children count of +a variable that has a synthetic child provider, notice that LLDB hides the +actual raw children. For example, suppose we have a ``std::vector``, which has +an actual in-memory property ``__begin`` marking the beginning of its data. +After the synthetic child provider is executed, the ``std::vector`` variable +won't show ``__begin`` as child anymore, even through the SB API. It will have +instead the children calculated by the provider. In case the actual raw +children are needed, a call to ``value.GetNonSyntheticValue()`` is enough to +get a raw version of the value. It is import to remember this when implementing +summary string providers, as they run after the synthetic child provider. + + In some cases, if LLDB is unable to use the real object to get a child specified in an expression path, it will automatically refer to the synthetic children. While in summaries it is best to always use ${svar to make your @@ -1024,6 +1109,39 @@ only need to see the ones named B, H and Q, you can define a filter: (std::string) Q = "Hello world" } +Callback-based type matching +---------------------------- + +Even though regular expression matching works well for the vast majority of data +formatters (you normally know the name of the type you're writing a formatter +for), there are some cases where it's useful to look at the type before deciding +what formatter to apply. + +As an example scenario, imagine we have a code generator that produces some +classes that inherit from a common ``GeneratedObject`` class, and we have a +summary function and a synthetic child provider that work for all +``GeneratedObject`` instances (they all follow the same pattern). However, there +is no common pattern in the name of these classes, so we can't register the +formatter neither by name nor by regular expression. + +In that case, you can write a recognizer function like this: + +:: + + def is_generated_object(sbtype, internal_dict): + for base in sbtype.get_bases_array(): + if base.GetName() == "GeneratedObject" + return True + return False + +And pass this function to ``type summary add`` and ``type synthetic add`` using +the flag ``--recognizer-function``. + +:: + + (lldb) type summary add --expand --python-function my_summary_function --recognizer-function is_generated_object + (lldb) type synthetic add --python-class my_child_provider --recognizer-function is_generated_object + Objective-C Dynamic Type Discovery ---------------------------------- @@ -1142,11 +1260,11 @@ not-empty category. Finding Formatters 101 ---------------------- -Searching for a formatter (including formats, starting in SVN rev r192217) -given a variable goes through a rather intricate set of rules. Namely, what -happens is that LLDB starts looking in each enabled category, according to the -order in which they were enabled (latest enabled first). In each category, LLDB -does the following: +Searching for a formatter (including formats, since lldb 3.4.0) given a +variable goes through a rather intricate set of rules. Namely, what happens is +that LLDB starts looking in each enabled category, according to the order in +which they were enabled (latest enabled first). In each category, LLDB does the +following: - If there is a formatter for the type of the variable, use it - If this object is a pointer, and there is a formatter for the pointee type diff --git a/gnu/llvm/lldb/examples/customization/bin-utils/binutils.py b/gnu/llvm/lldb/examples/customization/bin-utils/binutils.py index f1aa48fa26d..4237ab65250 100644 --- a/gnu/llvm/lldb/examples/customization/bin-utils/binutils.py +++ b/gnu/llvm/lldb/examples/customization/bin-utils/binutils.py @@ -1,7 +1,5 @@ "Collection of tools for displaying bit representation of numbers.""" -from __future__ import print_function - def binary(n, width=None): """ Return a list of (0|1)'s for the binary representation of n where n >= 0. diff --git a/gnu/llvm/lldb/examples/customization/import-python/importcmd.py b/gnu/llvm/lldb/examples/customization/import-python/importcmd.py index cf7ac979966..e355a09c7a3 100644 --- a/gnu/llvm/lldb/examples/customization/import-python/importcmd.py +++ b/gnu/llvm/lldb/examples/customization/import-python/importcmd.py @@ -1,4 +1,3 @@ -from __future__ import print_function import sys import os import lldb diff --git a/gnu/llvm/lldb/examples/customization/pwd-cd-and-system/utils.py b/gnu/llvm/lldb/examples/customization/pwd-cd-and-system/utils.py index 6c3c2540f3d..75dcb1a0db7 100644 --- a/gnu/llvm/lldb/examples/customization/pwd-cd-and-system/utils.py +++ b/gnu/llvm/lldb/examples/customization/pwd-cd-and-system/utils.py @@ -1,5 +1,4 @@ """Utility for changing directories and execution of commands in a subshell.""" -from __future__ import print_function import os import shlex diff --git a/gnu/llvm/lldb/examples/darwin/heap_find/heap.py b/gnu/llvm/lldb/examples/darwin/heap_find/heap.py index 8ee44ae25e4..38b549ca330 100644 --- a/gnu/llvm/lldb/examples/darwin/heap_find/heap.py +++ b/gnu/llvm/lldb/examples/darwin/heap_find/heap.py @@ -8,7 +8,6 @@ # (lldb) script import lldb.macosx.heap #---------------------------------------------------------------------- -from __future__ import print_function import lldb import optparse import os @@ -129,7 +128,7 @@ typedef struct malloc_zone_t { void *reserved1[12]; struct malloc_introspection_t *introspect; } malloc_zone_t; -kern_return_t malloc_get_all_zones(task_t task, memory_reader_t reader, vm_address_t **addresses, unsigned *count); +kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *); memory_reader_t task_peek = [](task_t, vm_address_t remote_address, vm_size_t, void **local_memory) -> kern_return_t { *local_memory = (void*) remote_address; return KERN_SUCCESS; @@ -1494,30 +1493,29 @@ int nc = (int)objc_getClassList(baton.classes, sizeof(baton.classes)/sizeof(Clas if __name__ == '__main__': lldb.debugger = lldb.SBDebugger.Create() -# Make the options so we can generate the help text for the new LLDB -# command line command prior to registering it with LLDB below. This way -# if clients in LLDB type "help malloc_info", they will see the exact same -# output as typing "malloc_info --help". -ptr_refs.__doc__ = get_ptr_refs_options().format_help() -cstr_refs.__doc__ = get_cstr_refs_options().format_help() -malloc_info.__doc__ = get_malloc_info_options().format_help() -objc_refs.__doc__ = get_objc_refs_options().format_help() -lldb.debugger.HandleCommand( - 'command script add -f %s.ptr_refs ptr_refs' % - __name__) -lldb.debugger.HandleCommand( - 'command script add -f %s.cstr_refs cstr_refs' % - __name__) -lldb.debugger.HandleCommand( - 'command script add -f %s.malloc_info malloc_info' % - __name__) -lldb.debugger.HandleCommand( - 'command script add -f %s.find_variable find_variable' % - __name__) -# lldb.debugger.HandleCommand('command script add -f %s.heap heap' % package_name) -# lldb.debugger.HandleCommand('command script add -f %s.section_ptr_refs section_ptr_refs' % package_name) -# lldb.debugger.HandleCommand('command script add -f %s.stack_ptr_refs stack_ptr_refs' % package_name) -lldb.debugger.HandleCommand( - 'command script add -f %s.objc_refs objc_refs' % - __name__) -print('"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.') +def __lldb_init_module(debugger, internal_dict): + # Make the options so we can generate the help text for the new LLDB + # command line command prior to registering it with LLDB below. This way + # if clients in LLDB type "help malloc_info", they will see the exact same + # output as typing "malloc_info --help". + ptr_refs.__doc__ = get_ptr_refs_options().format_help() + cstr_refs.__doc__ = get_cstr_refs_options().format_help() + malloc_info.__doc__ = get_malloc_info_options().format_help() + objc_refs.__doc__ = get_objc_refs_options().format_help() + debugger.HandleCommand( + 'command script add -o -f %s.ptr_refs ptr_refs' % + __name__) + debugger.HandleCommand( + 'command script add -o -f %s.cstr_refs cstr_refs' % + __name__) + debugger.HandleCommand( + 'command script add -o -f %s.malloc_info malloc_info' % + __name__) + debugger.HandleCommand( + 'command script add -o -f %s.find_variable find_variable' % + __name__) + # debugger.HandleCommand('command script add -o -f %s.section_ptr_refs section_ptr_refs' % package_name) + debugger.HandleCommand( + 'command script add -o -f %s.objc_refs objc_refs' % + __name__) + print('"malloc_info", "ptr_refs", "cstr_refs", "find_variable", and "objc_refs" commands have been installed, use the "--help" options on these commands for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/armv7_cortex_m_target_defintion.py b/gnu/llvm/lldb/examples/python/armv7_cortex_m_target_defintion.py index e8f39ccb09e..b1a84195e52 100755 --- a/gnu/llvm/lldb/examples/python/armv7_cortex_m_target_defintion.py +++ b/gnu/llvm/lldb/examples/python/armv7_cortex_m_target_defintion.py @@ -31,7 +31,7 @@ # # USAGE # -# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/armv7_cortex_m_target_defintion.py +# (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/armv7_cortex_m_target_definition.py # (lldb) gdb-remote other.baz.com:1234 # # The target definition file will get used if and only if the diff --git a/gnu/llvm/lldb/examples/python/bsd.py b/gnu/llvm/lldb/examples/python/bsd.py index fdf5455fe69..6dc5f735dc9 100755 --- a/gnu/llvm/lldb/examples/python/bsd.py +++ b/gnu/llvm/lldb/examples/python/bsd.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import cmd import optparse @@ -559,7 +558,7 @@ def __lldb_init_module(debugger, dict): # interpreter. # Add any commands contained in this module to LLDB debugger.HandleCommand( - 'command script add -c %s.VerifyDebugMapCommand %s' % ( + 'command script add -o -c %s.VerifyDebugMapCommand %s' % ( __name__, VerifyDebugMapCommand.name)) print('The "%s" command has been installed, type "help %s" for detailed ' 'help.' % (VerifyDebugMapCommand.name, VerifyDebugMapCommand.name)) diff --git a/gnu/llvm/lldb/examples/python/cmdtemplate.py b/gnu/llvm/lldb/examples/python/cmdtemplate.py index aa99e4c03be..439452a86ca 100644 --- a/gnu/llvm/lldb/examples/python/cmdtemplate.py +++ b/gnu/llvm/lldb/examples/python/cmdtemplate.py @@ -9,8 +9,6 @@ # (lldb) command script import /path/to/cmdtemplate.py # --------------------------------------------------------------------- -from __future__ import print_function - import inspect import lldb import optparse @@ -26,7 +24,7 @@ class FrameStatCommand: parser = cls.create_options() cls.__doc__ = parser.format_help() # Add any commands contained in this module to LLDB - command = 'command script add -c %s.%s %s' % (module_name, + command = 'command script add -o -c %s.%s %s' % (module_name, cls.__name__, cls.program) debugger.HandleCommand(command) diff --git a/gnu/llvm/lldb/examples/python/crashlog.py b/gnu/llvm/lldb/examples/python/crashlog.py index a7b2d3b52b5..6a5c560238e 100755 --- a/gnu/llvm/lldb/examples/python/crashlog.py +++ b/gnu/llvm/lldb/examples/python/crashlog.py @@ -26,10 +26,11 @@ # PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash #---------------------------------------------------------------------- -from __future__ import print_function -import cmd +import abc +import concurrent.futures +import contextlib import datetime -import glob +import json import optparse import os import platform @@ -39,9 +40,12 @@ import shlex import string import subprocess import sys +import threading import time import uuid -import json + + +print_lock = threading.RLock() try: # First try for LLDB in case PYTHONPATH is already correctly setup. @@ -49,11 +53,9 @@ try: except ImportError: # Ask the command line driver for the path to the lldb module. Copy over # the environment so that SDKROOT is propagated to xcrun. - env = os.environ.copy() - env['LLDB_DEFAULT_PYTHON_VERSION'] = str(sys.version_info.major) command = ['xcrun', 'lldb', '-P'] if platform.system() == 'Darwin' else ['lldb', '-P'] # Extend the PYTHONPATH if the path exists and isn't already there. - lldb_python_path = subprocess.check_output(command, env=env).decode("utf-8").strip() + lldb_python_path = subprocess.check_output(command).decode("utf-8").strip() if os.path.exists(lldb_python_path) and not sys.path.__contains__(lldb_python_path): sys.path.append(lldb_python_path) # Try importing LLDB again. @@ -65,7 +67,6 @@ except ImportError: from lldb.utils import symbolication - def read_plist(s): if sys.version_info.major == 3: return plistlib.loads(s) @@ -78,11 +79,14 @@ class CrashLog(symbolication.Symbolicator): def __init__(self, index, app_specific_backtrace): self.index = index + self.id = index self.frames = list() self.idents = list() self.registers = dict() self.reason = None + self.name = None self.queue = None + self.crashed = False self.app_specific_backtrace = app_specific_backtrace def dump(self, prefix): @@ -111,14 +115,12 @@ class CrashLog(symbolication.Symbolicator): for frame_idx, frame in enumerate(self.frames): disassemble = ( this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth - if frame_idx == 0: - symbolicated_frame_addresses = crash_log.symbolicate( - frame.pc & crash_log.addr_mask, options.verbose) - else: - # Any frame above frame zero and we have to subtract one to - # get the previous line entry - symbolicated_frame_addresses = crash_log.symbolicate( - (frame.pc & crash_log.addr_mask) - 1, options.verbose) + + # Except for the zeroth frame, we should subtract 1 from every + # frame pc to get the previous line entry. + pc = frame.pc & crash_log.addr_mask + pc = pc if frame_idx == 0 or pc == 0 else pc - 1 + symbolicated_frame_addresses = crash_log.symbolicate(pc, options.verbose) if symbolicated_frame_addresses: symbolicated_frame_address_idx = 0 @@ -160,6 +162,9 @@ class CrashLog(symbolication.Symbolicator): print() for reg in self.registers.keys(): print(" %-8s = %#16.16x" % (reg, self.registers[reg])) + elif self.crashed: + print() + print("No thread state (register information) available") def add_ident(self, ident): if ident not in self.idents: @@ -265,7 +270,8 @@ class CrashLog(symbolication.Symbolicator): self.resolved = True uuid_str = self.get_normalized_uuid_string() if self.show_symbol_progress(): - print('Getting symbols for %s %s...' % (uuid_str, self.path), end=' ') + with print_lock: + print('Getting symbols for %s %s...' % (uuid_str, self.path)) if os.path.exists(self.dsymForUUIDBinary): dsym_for_uuid_command = '%s %s' % ( self.dsymForUUIDBinary, uuid_str) @@ -274,7 +280,8 @@ class CrashLog(symbolication.Symbolicator): try: plist_root = read_plist(s) except: - print(("Got exception: ", sys.exc_info()[1], " handling dsymForUUID output: \n", s)) + with print_lock: + print(("Got exception: ", sys.exc_info()[1], " handling dsymForUUID output: \n", s)) raise if plist_root: plist = plist_root[uuid_str] @@ -293,23 +300,31 @@ class CrashLog(symbolication.Symbolicator): return False if not self.resolved_path and not os.path.exists(self.path): try: - dsym = subprocess.check_output( + mdfind_results = subprocess.check_output( ["/usr/bin/mdfind", - "com_apple_xcode_dsym_uuids == %s"%uuid_str]).decode("utf-8")[:-1] - if dsym and os.path.exists(dsym): - print(('falling back to binary inside "%s"'%dsym)) - self.symfile = dsym + "com_apple_xcode_dsym_uuids == %s" % uuid_str]).decode("utf-8").splitlines() + found_matching_slice = False + for dsym in mdfind_results: dwarf_dir = os.path.join(dsym, 'Contents/Resources/DWARF') + if not os.path.exists(dwarf_dir): + # Not a dSYM bundle, probably an Xcode archive. + continue + with print_lock: + print('falling back to binary inside "%s"' % dsym) + self.symfile = dsym for filename in os.listdir(dwarf_dir): - self.path = os.path.join(dwarf_dir, filename) - if not self.find_matching_slice(): - return False - break + self.path = os.path.join(dwarf_dir, filename) + if self.find_matching_slice(): + found_matching_slice = True + break + if found_matching_slice: + break except: pass if (self.resolved_path and os.path.exists(self.resolved_path)) or ( self.path and os.path.exists(self.path)): - print('ok') + with print_lock: + print('Resolved symbols for %s %s...' % (uuid_str, self.path)) return True else: self.unavailable = True @@ -324,6 +339,8 @@ class CrashLog(symbolication.Symbolicator): self.threads = list() self.backtraces = list() # For application specific backtraces self.idents = list() # A list of the required identifiers for doing all stack backtraces + self.errors = list() + self.exception = dict() self.crashed_thread_idx = -1 self.version = -1 self.target = None @@ -342,6 +359,12 @@ class CrashLog(symbolication.Symbolicator): for image in self.images: image.dump(' ') + def set_main_image(self, identifier): + for i, image in enumerate(self.images): + if image.identifier == identifier: + self.images.insert(0, self.images.pop(i)) + break + def find_image_with_identifier(self, identifier): for image in self.images: if image.identifier == identifier: @@ -388,39 +411,64 @@ class CrashLogFormatException(Exception): class CrashLogParseException(Exception): - pass + pass +class InteractiveCrashLogException(Exception): + pass class CrashLogParser: - def parse(self, debugger, path, verbose): - try: - return JSONCrashLogParser(debugger, path, verbose).parse() - except CrashLogFormatException: - return TextCrashLogParser(debugger, path, verbose).parse() - + @staticmethod + def create(debugger, path, verbose): + data = JSONCrashLogParser.is_valid_json(path) + if data: + parser = JSONCrashLogParser(debugger, path, verbose) + parser.data = data + return parser + else: + return TextCrashLogParser(debugger, path, verbose) -class JSONCrashLogParser: def __init__(self, debugger, path, verbose): self.path = os.path.expanduser(path) self.verbose = verbose self.crashlog = CrashLog(debugger, self.path, self.verbose) + @abc.abstractmethod def parse(self): - with open(self.path, 'r') as f: - buffer = f.read() + pass + - # First line is meta-data. - buffer = buffer[buffer.index('\n') + 1:] +class JSONCrashLogParser(CrashLogParser): + @staticmethod + def is_valid_json(path): + def parse_json(buffer): + try: + return json.loads(buffer) + except: + # The first line can contain meta data. Try stripping it and + # try again. + head, _, tail = buffer.partition('\n') + return json.loads(tail) + with open(path, 'r', encoding='utf-8') as f: + buffer = f.read() try: - self.data = json.loads(buffer) - except ValueError: - raise CrashLogFormatException() + return parse_json(buffer) + except: + return None + def parse(self): try: self.parse_process_info(self.data) self.parse_images(self.data['usedImages']) + self.parse_main_image(self.data) self.parse_threads(self.data['threads']) + if 'asi' in self.data: + self.crashlog.asi = self.data['asi'] + if 'asiBacktraces' in self.data: + self.parse_app_specific_backtraces(self.data['asiBacktraces']) + if 'lastExceptionBacktrace' in self.data: + self.crashlog.asb = self.data['lastExceptionBacktrace'] + self.parse_errors(self.data) thread = self.crashlog.threads[self.crashlog.crashed_thread_idx] reason = self.parse_crash_reason(self.data['exception']) if thread.reason: @@ -440,18 +488,21 @@ class JSONCrashLogParser: def parse_process_info(self, json_data): self.crashlog.process_id = json_data['pid'] self.crashlog.process_identifier = json_data['procName'] - self.crashlog.process_path = json_data['procPath'] def parse_crash_reason(self, json_exception): + self.crashlog.exception = json_exception exception_type = json_exception['type'] - exception_signal = json_exception['signal'] + exception_signal = " " + if 'signal' in json_exception: + exception_signal += "({})".format(json_exception['signal']) + if 'codes' in json_exception: exception_extra = " ({})".format(json_exception['codes']) elif 'subtype' in json_exception: exception_extra = " ({})".format(json_exception['subtype']) else: exception_extra = "" - return "{} ({}){}".format(exception_type, exception_signal, + return "{}{}{}".format(exception_type, exception_signal, exception_extra) def parse_images(self, json_images): @@ -469,11 +520,17 @@ class JSONCrashLogParser: self.crashlog.images.append(darwin_image) idx += 1 + def parse_main_image(self, json_data): + if 'procName' in json_data: + proc_name = json_data['procName'] + self.crashlog.set_main_image(proc_name) + def parse_frames(self, thread, json_frames): idx = 0 for json_frame in json_frames: image_id = int(json_frame['imageIndex']) - ident = self.get_used_image(image_id)['name'] + json_image = self.get_used_image(image_id) + ident = json_image['name'] if 'name' in json_image else '' thread.add_ident(ident) if ident not in self.crashlog.idents: self.crashlog.idents.append(ident) @@ -482,6 +539,23 @@ class JSONCrashLogParser: image_addr = self.get_used_image(image_id)['base'] pc = image_addr + frame_offset thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + + # on arm64 systems, if it jump through a null function pointer, + # we end up at address 0 and the crash reporter unwinder + # misses the frame that actually faulted. + # But $lr can tell us where the last BL/BLR instruction used + # was at, so insert that address as the caller stack frame. + if idx == 0 and pc == 0 and "lr" in thread.registers: + pc = thread.registers["lr"] + for image in self.data['usedImages']: + text_lo = image['base'] + text_hi = text_lo + image['size'] + if text_lo <= pc < text_hi: + idx += 1 + frame_offset = pc - text_lo + thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + break + idx += 1 def parse_threads(self, json_threads): @@ -489,26 +563,68 @@ class JSONCrashLogParser: for json_thread in json_threads: thread = self.crashlog.Thread(idx, False) if 'name' in json_thread: + thread.name = json_thread['name'] thread.reason = json_thread['name'] + if 'id' in json_thread: + thread.id = int(json_thread['id']) if json_thread.get('triggered', False): self.crashlog.crashed_thread_idx = idx - thread.registers = self.parse_thread_registers( - json_thread['threadState']) - thread.queue = json_thread.get('queue') + thread.crashed = True + if 'threadState' in json_thread: + thread.registers = self.parse_thread_registers( + json_thread['threadState']) + if 'queue' in json_thread: + thread.queue = json_thread.get('queue') self.parse_frames(thread, json_thread.get('frames', [])) self.crashlog.threads.append(thread) idx += 1 - def parse_thread_registers(self, json_thread_state): + def parse_asi_backtrace(self, thread, bt): + for line in bt.split('\n'): + frame_match = TextCrashLogParser.frame_regex.search(line) + if not frame_match: + print("error: can't parse application specific backtrace.") + return False + + (frame_id, frame_img_name, frame_addr, + frame_ofs) = frame_match.groups() + + thread.add_ident(frame_img_name) + if frame_img_name not in self.crashlog.idents: + self.crashlog.idents.append(frame_img_name) + thread.frames.append(self.crashlog.Frame(int(frame_id), int( + frame_addr, 0), frame_ofs)) + + return True + + def parse_app_specific_backtraces(self, json_app_specific_bts): + for idx, backtrace in enumerate(json_app_specific_bts): + thread = self.crashlog.Thread(idx, True) + thread.queue = "Application Specific Backtrace" + if self.parse_asi_backtrace(thread, backtrace): + self.crashlog.threads.append(thread) + + def parse_thread_registers(self, json_thread_state, prefix=None): registers = dict() for key, state in json_thread_state.items(): + if key == "rosetta": + registers.update(self.parse_thread_registers(state)) + continue + if key == "x": + gpr_dict = { str(idx) : reg for idx,reg in enumerate(state) } + registers.update(self.parse_thread_registers(gpr_dict, key)) + continue try: - value = int(state['value']) - registers[key] = value - except (TypeError, ValueError): - pass + value = int(state['value']) + registers["{}{}".format(prefix or '',key)] = value + except (KeyError, ValueError, TypeError): + pass return registers + def parse_errors(self, json_data): + if 'reportNotes' in json_data: + self.crashlog.errors = json_data['reportNotes'] + class CrashLogParseMode: NORMAL = 0 @@ -518,37 +634,36 @@ class CrashLogParseMode: SYSTEM = 4 INSTRS = 5 - -class TextCrashLogParser: - parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]') - thread_state_regex = re.compile('^Thread ([0-9]+) crashed with') - thread_instrs_regex = re.compile('^Thread ([0-9]+) instruction stream') - thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)') - app_backtrace_regex = re.compile('^Application Specific Backtrace ([0-9]+)([^:]*):(.*)') - version = r'(\(.+\)|(arm|x86_)[0-9a-z]+)\s+' - frame_regex = re.compile(r'^([0-9]+)' r'\s' # id - r'+(.+?)' r'\s+' # img_name - r'(' +version+ r')?' # img_version - r'(0x[0-9a-fA-F]{7}[0-9a-fA-F]+)' # addr - r' +(.*)' # offs +class TextCrashLogParser(CrashLogParser): + parent_process_regex = re.compile(r'^Parent Process:\s*(.*)\[(\d+)\]') + thread_state_regex = re.compile(r'^Thread \d+ crashed with') + thread_instrs_regex = re.compile(r'^Thread \d+ instruction stream') + thread_regex = re.compile(r'^Thread (\d+).*:') + app_backtrace_regex = re.compile(r'^Application Specific Backtrace (\d+).*:') + version = r'\(.+\)|(?:arm|x86_)[0-9a-z]+' + frame_regex = re.compile(r'^(\d+)\s+' # id + r'(.+?)\s+' # img_name + r'(?:' +version+ r'\s+)?' # img_version + r'(0x[0-9a-fA-F]{4,})' # addr (4 chars or more) + r'(?: +(.*))?' # offs ) - null_frame_regex = re.compile(r'^([0-9]+)\s+\?\?\?\s+(0{7}0+) +(.*)') - image_regex_uuid = re.compile(r'(0x[0-9a-fA-F]+)' # img_lo - r'\s+' '-' r'\s+' # - - r'(0x[0-9a-fA-F]+)' r'\s+' # img_hi - r'[+]?(.+?)' r'\s+' # img_name - r'(' +version+ ')?' # img_version - r'(<([-0-9a-fA-F]+)>\s+)?' # img_uuid - r'(/.*)' # img_path + null_frame_regex = re.compile(r'^\d+\s+\?\?\?\s+0{4,} +') + image_regex_uuid = re.compile(r'(0x[0-9a-fA-F]+)' # img_lo + r'\s+-\s+' # - + r'(0x[0-9a-fA-F]+)\s+' # img_hi + r'[+]?(.+?)\s+' # img_name + r'(?:(' +version+ r')\s+)?' # img_version + r'(?:<([-0-9a-fA-F]+)>\s+)?' # img_uuid + r'(\?+|/.*)' # img_path ) - + exception_type_regex = re.compile(r'^Exception Type:\s+(EXC_[A-Z_]+)(?:\s+\((.*)\))?') + exception_codes_regex = re.compile(r'^Exception Codes:\s+(0x[0-9a-fA-F]+),\s*(0x[0-9a-fA-F]+)') + exception_extra_regex = re.compile(r'^Exception\s+.*:\s+(.*)') def __init__(self, debugger, path, verbose): - self.path = os.path.expanduser(path) - self.verbose = verbose + super().__init__(debugger, path, verbose) self.thread = None self.app_specific_backtrace = False - self.crashlog = CrashLog(debugger, self.path, self.verbose) self.parse_mode = CrashLogParseMode.NORMAL self.parsers = { CrashLogParseMode.NORMAL : self.parse_normal, @@ -560,7 +675,7 @@ class TextCrashLogParser: } def parse(self): - with open(self.path,'r') as f: + with open(self.path,'r', encoding='utf-8') as f: lines = f.read().splitlines() for line in lines: @@ -570,9 +685,9 @@ class TextCrashLogParser: if self.parse_mode == CrashLogParseMode.THREAD: if self.thread.index == self.crashlog.crashed_thread_idx: self.thread.reason = '' - if self.crashlog.thread_exception: + if hasattr(self.crashlog, 'thread_exception'): self.thread.reason += self.crashlog.thread_exception - if self.crashlog.thread_exception_data: + if hasattr(self.crashlog, 'thread_exception_data'): self.thread.reason += " (%s)" % self.crashlog.thread_exception_data if self.app_specific_backtrace: self.crashlog.backtraces.append(self.thread) @@ -590,14 +705,43 @@ class TextCrashLogParser: return self.crashlog + def parse_exception(self, line): + if not line.startswith('Exception'): + return + if line.startswith('Exception Type:'): + self.crashlog.thread_exception = line[15:].strip() + exception_type_match = self.exception_type_regex.search(line) + if exception_type_match: + exc_type, exc_signal = exception_type_match.groups() + self.crashlog.exception['type'] = exc_type + if exc_signal: + self.crashlog.exception['signal'] = exc_signal + elif line.startswith('Exception Subtype:'): + self.crashlog.thread_exception_subtype = line[18:].strip() + if 'type' in self.crashlog.exception: + self.crashlog.exception['subtype'] = self.crashlog.thread_exception_subtype + elif line.startswith('Exception Codes:'): + self.crashlog.thread_exception_data = line[16:].strip() + if 'type' not in self.crashlog.exception: + return + exception_codes_match = self.exception_codes_regex.search(line) + if exception_codes_match: + self.crashlog.exception['codes'] = self.crashlog.thread_exception_data + code, subcode = exception_codes_match.groups() + self.crashlog.exception['rawCodes'] = [int(code, base=16), + int(subcode, base=16)] + else: + if 'type' not in self.crashlog.exception: + return + exception_extra_match = self.exception_extra_regex.search(line) + if exception_extra_match: + self.crashlog.exception['message'] = exception_extra_match.group(1) def parse_normal(self, line): if line.startswith('Process:'): (self.crashlog.process_name, pid_with_brackets) = line[ 8:].strip().split(' [') self.crashlog.process_id = pid_with_brackets.strip('[]') - elif line.startswith('Path:'): - self.crashlog.process_path = line[5:].strip() elif line.startswith('Identifier:'): self.crashlog.process_identifier = line[11:].strip() elif line.startswith('Version:'): @@ -615,14 +759,8 @@ class TextCrashLogParser: line) self.crashlog.parent_process_name = parent_process_match.group(1) self.crashlog.parent_process_id = parent_process_match.group(2) - elif line.startswith('Exception Type:'): - self.crashlog.thread_exception = line[15:].strip() - return - elif line.startswith('Exception Codes:'): - self.crashlog.thread_exception_data = line[16:].strip() - return - elif line.startswith('Exception Subtype:'): # iOS - self.crashlog.thread_exception_data = line[18:].strip() + elif line.startswith('Exception'): + self.parse_exception(line) return elif line.startswith('Crashed Thread:'): self.crashlog.crashed_thread_idx = int(line[15:].strip().split()[0]) @@ -690,8 +828,8 @@ class TextCrashLogParser: return frame_match = self.frame_regex.search(line) if frame_match: - (frame_id, frame_img_name, _, frame_img_version, _, - frame_addr, frame_ofs) = frame_match.groups() + (frame_id, frame_img_name, frame_addr, + frame_ofs) = frame_match.groups() ident = frame_img_name self.thread.add_ident(ident) if ident not in self.crashlog.idents: @@ -704,8 +842,8 @@ class TextCrashLogParser: def parse_images(self, line): image_match = self.image_regex_uuid.search(line) if image_match: - (img_lo, img_hi, img_name, _, img_version, _, - _, img_uuid, img_path) = image_match.groups() + (img_lo, img_hi, img_name, img_version, + img_uuid, img_path) = image_match.groups() image = self.crashlog.DarwinImage(int(img_lo, 0), int(img_hi, 0), img_name.strip(), img_version.strip() @@ -718,13 +856,10 @@ class TextCrashLogParser: def parse_thread_registers(self, line): - stripped_line = line.strip() # "r12: 0x00007fff6b5939c8 r13: 0x0000000007000006 r14: 0x0000000000002a03 r15: 0x0000000000000c00" - reg_values = re.findall( - '([a-zA-Z0-9]+: 0[Xx][0-9a-fA-F]+) *', stripped_line) - for reg_value in reg_values: - (reg, value) = reg_value.split(': ') - self.thread.registers[reg.strip()] = int(value, 0) + reg_values = re.findall('([a-z0-9]+): (0x[0-9a-f]+)', line, re.I) + for reg, value in reg_values: + self.thread.registers[reg] = int(value, 16) def parse_system(self, line): self.crashlog.system_profile.append(line) @@ -738,138 +873,6 @@ def usage(): sys.exit(0) -class Interactive(cmd.Cmd): - '''Interactive prompt for analyzing one or more Darwin crash logs, type "help" to see a list of supported commands.''' - image_option_parser = None - - def __init__(self, crash_logs): - cmd.Cmd.__init__(self) - self.use_rawinput = False - self.intro = 'Interactive crashlogs prompt, type "help" to see a list of supported commands.' - self.crash_logs = crash_logs - self.prompt = '% ' - - def default(self, line): - '''Catch all for unknown command, which will exit the interpreter.''' - print("uknown command: %s" % line) - return True - - def do_q(self, line): - '''Quit command''' - return True - - def do_quit(self, line): - '''Quit command''' - return True - - def do_symbolicate(self, line): - description = '''Symbolicate one or more darwin crash log files by index to provide source file and line information, - inlined stack frames back to the concrete functions, and disassemble the location of the crash - for the first frame of the crashed thread.''' - option_parser = CreateSymbolicateCrashLogOptions( - 'symbolicate', description, False) - command_args = shlex.split(line) - try: - (options, args) = option_parser.parse_args(command_args) - except: - return - - if args: - # We have arguments, they must valid be crash log file indexes - for idx_str in args: - idx = int(idx_str) - if idx < len(self.crash_logs): - SymbolicateCrashLog(self.crash_logs[idx], options) - else: - print('error: crash log index %u is out of range' % (idx)) - else: - # No arguments, symbolicate all crash logs using the options - # provided - for idx in range(len(self.crash_logs)): - SymbolicateCrashLog(self.crash_logs[idx], options) - - def do_list(self, line=None): - '''Dump a list of all crash logs that are currently loaded. - - USAGE: list''' - print('%u crash logs are loaded:' % len(self.crash_logs)) - for (crash_log_idx, crash_log) in enumerate(self.crash_logs): - print('[%u] = %s' % (crash_log_idx, crash_log.path)) - - def do_image(self, line): - '''Dump information about one or more binary images in the crash log given an image basename, or all images if no arguments are provided.''' - usage = "usage: %prog [options] [PATH ...]" - description = '''Dump information about one or more images in all crash logs. The can be a full path, image basename, or partial path. Searches are done in this order.''' - command_args = shlex.split(line) - if not self.image_option_parser: - self.image_option_parser = optparse.OptionParser( - description=description, prog='image', usage=usage) - self.image_option_parser.add_option( - '-a', - '--all', - action='store_true', - help='show all images', - default=False) - try: - (options, args) = self.image_option_parser.parse_args(command_args) - except: - return - - if args: - for image_path in args: - fullpath_search = image_path[0] == '/' - for (crash_log_idx, crash_log) in enumerate(self.crash_logs): - matches_found = 0 - for (image_idx, image) in enumerate(crash_log.images): - if fullpath_search: - if image.get_resolved_path() == image_path: - matches_found += 1 - print('[%u] ' % (crash_log_idx), image) - else: - image_basename = image.get_resolved_path_basename() - if image_basename == image_path: - matches_found += 1 - print('[%u] ' % (crash_log_idx), image) - if matches_found == 0: - for (image_idx, image) in enumerate(crash_log.images): - resolved_image_path = image.get_resolved_path() - if resolved_image_path and string.find( - image.get_resolved_path(), image_path) >= 0: - print('[%u] ' % (crash_log_idx), image) - else: - for crash_log in self.crash_logs: - for (image_idx, image) in enumerate(crash_log.images): - print('[%u] %s' % (image_idx, image)) - return False - - -def interactive_crashlogs(debugger, options, args): - crash_log_files = list() - for arg in args: - for resolved_path in glob.glob(arg): - crash_log_files.append(resolved_path) - - crash_logs = list() - for crash_log_file in crash_log_files: - try: - crash_log = CrashLogParser().parse(debugger, crash_log_file, options.verbose) - except Exception as e: - print(e) - continue - if options.debug: - crash_log.dump() - if not crash_log.images: - print('error: no images in crash log "%s"' % (crash_log)) - continue - else: - crash_logs.append(crash_log) - - interpreter = Interactive(crash_logs) - # List all crash logs that were imported - interpreter.do_list() - interpreter.cmdloop() - - def save_crashlog(debugger, command, exe_ctx, result, dict): usage = "usage: %prog [options] " description = '''Export the state of current target into a crashlog file''' @@ -893,7 +896,7 @@ def save_crashlog(debugger, command, exe_ctx, result, dict): result.PutCString( "error: invalid arguments, a single output file is the only valid argument") return - out_file = open(args[0], 'w') + out_file = open(args[0], 'w', encoding='utf-8') if not out_file: result.PutCString( "error: failed to open file '%s' for writing...", @@ -978,11 +981,19 @@ def save_crashlog(debugger, command, exe_ctx, result, dict): result.PutCString("error: invalid target") -def Symbolicate(debugger, command, result, dict): - try: - SymbolicateCrashLogs(debugger, shlex.split(command)) - except Exception as e: - result.PutCString("error: python exception: %s" % e) +class Symbolicate: + def __init__(self, debugger, internal_dict): + pass + + def __call__(self, debugger, command, exe_ctx, result): + SymbolicateCrashLogs(debugger, shlex.split(command), result) + + def get_short_help(self): + return "Symbolicate one or more darwin crash log files." + + def get_long_help(self): + option_parser = CrashLogOptionParser() + return option_parser.format_help() def SymbolicateCrashLog(crash_log, options): @@ -1031,9 +1042,16 @@ def SymbolicateCrashLog(crash_log, options): else: print('error: can\'t find image for identifier "%s"' % ident) - for image in images_to_load: - if image not in loaded_images: - err = image.add_module(target) + futures = [] + with concurrent.futures.ThreadPoolExecutor() as executor: + def add_module(image, target): + return image, image.add_module(target) + + for image in images_to_load: + futures.append(executor.submit(add_module, image=image, target=target)) + + for future in concurrent.futures.as_completed(futures): + image, err = future.result() if err: print(err) else: @@ -1048,6 +1066,78 @@ def SymbolicateCrashLog(crash_log, options): thread.dump_symbolicated(crash_log, options) print() + if crash_log.errors: + print("Errors:") + for error in crash_log.errors: + print(error) + +def load_crashlog_in_scripted_process(debugger, crash_log_file, options, result): + crashlog_path = os.path.expanduser(crash_log_file) + if not os.path.exists(crashlog_path): + raise InteractiveCrashLogException("crashlog file %s does not exist" % crashlog_path) + + crashlog = CrashLogParser.create(debugger, crashlog_path, False).parse() + + target = lldb.SBTarget() + # 1. Try to use the user-provided target + if options.target_path: + target = debugger.CreateTarget(options.target_path) + if not target: + raise InteractiveCrashLogException("couldn't create target provided by the user (%s)" % options.target_path) + + # 2. If the user didn't provide a target, try to create a target using the symbolicator + if not target or not target.IsValid(): + target = crashlog.create_target() + # 3. If that didn't work, and a target is already loaded, use it + if (target is None or not target.IsValid()) and debugger.GetNumTargets() > 0: + target = debugger.GetTargetAtIndex(0) + # 4. Fail + if target is None or not target.IsValid(): + raise InteractiveCrashLogException("couldn't create target") + + ci = debugger.GetCommandInterpreter() + if not ci: + raise InteractiveCrashLogException("couldn't get command interpreter") + + ci.HandleCommand('script from lldb.macosx import crashlog_scripted_process', result) + if not result.Succeeded(): + raise InteractiveCrashLogException("couldn't import crashlog scripted process module") + + structured_data = lldb.SBStructuredData() + structured_data.SetFromJSON(json.dumps({ "file_path" : crashlog_path, + "load_all_images": options.load_all_images })) + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetProcessPluginName("ScriptedProcess") + launch_info.SetScriptedProcessClassName("crashlog_scripted_process.CrashLogScriptedProcess") + launch_info.SetScriptedProcessDictionary(structured_data) + error = lldb.SBError() + process = target.Launch(launch_info, error) + + if not process or error.Fail(): + raise InteractiveCrashLogException("couldn't launch Scripted Process", error) + + if not options.skip_status: + @contextlib.contextmanager + def synchronous(debugger): + async_state = debugger.GetAsync() + debugger.SetAsync(False) + try: + yield + finally: + debugger.SetAsync(async_state) + + with synchronous(debugger): + run_options = lldb.SBCommandInterpreterRunOptions() + run_options.SetStopOnError(True) + run_options.SetStopOnCrash(True) + run_options.SetEchoCommands(True) + + commands_stream = lldb.SBStream() + commands_stream.Print("process status --verbose\n") + commands_stream.Print("thread backtrace --extended true\n") + error = debugger.SetInputString(commands_stream.GetData()) + if error.Success(): + debugger.RunCommandInterpreter(True, False, run_options, 0, False, True) def CreateSymbolicateCrashLogOptions( command_name, @@ -1056,6 +1146,13 @@ def CreateSymbolicateCrashLogOptions( usage = "usage: %prog [options] [FILE ...]" option_parser = optparse.OptionParser( description=description, prog='crashlog', usage=usage) + option_parser.add_option( + '--version', + '-V', + dest='version', + action='store_true', + help='Show crashlog version', + default=False) option_parser.add_option( '--verbose', '-v', @@ -1075,7 +1172,9 @@ def CreateSymbolicateCrashLogOptions( '-a', action='store_true', dest='load_all_images', - help='load all executable images, not just the images found in the crashed stack frames', + help='load all executable images, not just the images found in the ' + 'crashed stack frames, loads stackframes for all the threads in ' + 'interactive mode.', default=False) option_parser.add_option( '--images', @@ -1151,12 +1250,31 @@ def CreateSymbolicateCrashLogOptions( '-i', '--interactive', action='store_true', - help='parse all crash logs and enter interactive mode', + help='parse a crash log and load it in a ScriptedProcess', + default=False) + option_parser.add_option( + '-b', + '--batch', + action='store_true', + help='dump symbolicated stackframes without creating a debug session', + default=True) + option_parser.add_option( + '--target', + '-t', + dest='target_path', + help='the target binary path that should be used for interactive crashlog (optional)', + default=None) + option_parser.add_option( + '--skip-status', + '-s', + dest='skip_status', + action='store_true', + help='prevent the interactive crashlog to dump the process status and thread backtrace at launch', default=False) return option_parser -def SymbolicateCrashLogs(debugger, command_args): +def CrashLogOptionParser(): description = '''Symbolicate one or more darwin crash log files to provide source file and line information, inlined stack frames back to the concrete functions, and disassemble the location of the crash for the first frame of the crashed thread. @@ -1165,13 +1283,24 @@ for use at the LLDB command line. After a crash log has been parsed and symbolic created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows you to explore the program as if it were stopped at the locations described in the crash log and functions can be disassembled and lookups can be performed using the addresses found in the crash log.''' - option_parser = CreateSymbolicateCrashLogOptions( - 'crashlog', description, True) + return CreateSymbolicateCrashLogOptions('crashlog', description, True) + +def SymbolicateCrashLogs(debugger, command_args, result): + option_parser = CrashLogOptionParser() + + if not len(command_args): + option_parser.print_help() + return + try: (options, args) = option_parser.parse_args(command_args) except: return + if options.version: + print(debugger.GetVersionString()) + return + if options.debug: print('command_args = %s' % command_args) print('options', options) @@ -1182,20 +1311,41 @@ be disassembled and lookups can be performed using the addresses found in the cr time.sleep(options.debug_delay) error = lldb.SBError() - if args: + def should_run_in_interactive_mode(options, ci): if options.interactive: - interactive_crashlogs(debugger, options, args) + return True + elif options.batch: + return False + # elif ci and ci.IsInteractive(): + # return True else: - for crash_log_file in args: - crash_log = CrashLogParser().parse(debugger, crash_log_file, options.verbose) + return False + + ci = debugger.GetCommandInterpreter() + + if args: + for crash_log_file in args: + if should_run_in_interactive_mode(options, ci): + try: + load_crashlog_in_scripted_process(debugger, crash_log_file, + options, result) + except InteractiveCrashLogException as e: + result.SetError(str(e)) + else: + crash_log = CrashLogParser.create(debugger, crash_log_file, options.verbose).parse() SymbolicateCrashLog(crash_log, options) + if __name__ == '__main__': # Create a new debugger instance debugger = lldb.SBDebugger.Create() - SymbolicateCrashLogs(debugger, sys.argv[1:]) + result = lldb.SBCommandReturnObject() + SymbolicateCrashLogs(debugger, sys.argv[1:], result) lldb.SBDebugger.Destroy(debugger) -elif getattr(lldb, 'debugger', None): - lldb.debugger.HandleCommand( - 'command script add -f lldb.macosx.crashlog.Symbolicate crashlog') - lldb.debugger.HandleCommand( - 'command script add -f lldb.macosx.crashlog.save_crashlog save_crashlog') + +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand( + 'command script add -o -c lldb.macosx.crashlog.Symbolicate crashlog') + debugger.HandleCommand( + 'command script add -o -f lldb.macosx.crashlog.save_crashlog save_crashlog') + print('"crashlog" and "save_crashlog" commands have been installed, use ' + 'the "--help" options on these commands for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/delta.py b/gnu/llvm/lldb/examples/python/delta.py index 0176fb0b334..3fcd090bae6 100755 --- a/gnu/llvm/lldb/examples/python/delta.py +++ b/gnu/llvm/lldb/examples/python/delta.py @@ -16,8 +16,6 @@ # available. #---------------------------------------------------------------------- -from __future__ import print_function - import optparse import os import shlex @@ -125,11 +123,10 @@ if __name__ == '__main__': import sys parse_time_log_args(sys.argv[1:]) -else: - import lldb - if lldb.debugger: + +def __lldb_init_module(debugger, internal_dict): # This initializer is being run from LLDB in the embedded command interpreter # Add any commands contained in this module to LLDB - lldb.debugger.HandleCommand( - 'command script add -f delta.parse_time_log parse_time_log') + debugger.HandleCommand( + 'command script add -o -f delta.parse_time_log parse_time_log') print('The "parse_time_log" command is now installed and ready for use, type "parse_time_log --help" for more information') diff --git a/gnu/llvm/lldb/examples/python/diagnose_nsstring.py b/gnu/llvm/lldb/examples/python/diagnose_nsstring.py index 4a8eee3c2dd..75158153e3b 100644 --- a/gnu/llvm/lldb/examples/python/diagnose_nsstring.py +++ b/gnu/llvm/lldb/examples/python/diagnose_nsstring.py @@ -4,8 +4,6 @@ # decisions it did and providing some useful context information that can # be used for improving the formatter -from __future__ import print_function - import lldb @@ -177,7 +175,7 @@ struct $__lldb__CFString {\ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand( - "command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % + "command script add -o -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__) print('The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/diagnose_unwind.py b/gnu/llvm/lldb/examples/python/diagnose_unwind.py index db3ff1952f3..0b994277073 100644 --- a/gnu/llvm/lldb/examples/python/diagnose_unwind.py +++ b/gnu/llvm/lldb/examples/python/diagnose_unwind.py @@ -5,7 +5,6 @@ # information about the stack frames, and tries an alternate unwind # algorithm, that will help to understand why lldb's unwind algorithm # did not succeed. -from __future__ import print_function import optparse import lldb @@ -308,7 +307,8 @@ def create_diagnose_unwind_options(): usage=usage) return parser -lldb.debugger.HandleCommand( - 'command script add -f %s.diagnose_unwind diagnose-unwind' % - __name__) -print('The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.') +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand( + 'command script add -o -f %s.diagnose_unwind diagnose-unwind' % + __name__) + print('The "diagnose-unwind" command has been installed, type "help diagnose-unwind" for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/disassembly_mode.py b/gnu/llvm/lldb/examples/python/disassembly_mode.py index 19647cc6555..18a1527dbd2 100644 --- a/gnu/llvm/lldb/examples/python/disassembly_mode.py +++ b/gnu/llvm/lldb/examples/python/disassembly_mode.py @@ -45,4 +45,4 @@ class DisassemblyMode: return "Toggles between a disassembly only mode and normal source mode\n" def __lldb_init_module(debugger, unused): - debugger.HandleCommand("command script add -c disassembly_mode.DisassemblyMode toggle-disassembly") + debugger.HandleCommand("command script add -o -c disassembly_mode.DisassemblyMode toggle-disassembly") diff --git a/gnu/llvm/lldb/examples/python/gdb_disassemble.py b/gnu/llvm/lldb/examples/python/gdb_disassemble.py index 65983e2e993..345277e85f1 100755 --- a/gnu/llvm/lldb/examples/python/gdb_disassemble.py +++ b/gnu/llvm/lldb/examples/python/gdb_disassemble.py @@ -21,6 +21,7 @@ def disassemble(debugger, command, result, dict): print("<%s + %-4u> 0x%x %8s %s" % (name, inst_offset, inst_addr, inst.mnemonic, inst.operands)) # Install the command when the module gets imported -lldb.debugger.HandleCommand( - 'command script add -f gdb_disassemble.disassemble gdb-disassemble') -print('Installed "gdb-disassemble" command for disassembly') +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand( + 'command script add -o -f gdb_disassemble.disassemble gdb-disassemble') + print('Installed "gdb-disassemble" command for disassembly') diff --git a/gnu/llvm/lldb/examples/python/gdbremote.py b/gnu/llvm/lldb/examples/python/gdbremote.py index 804977259de..8d000c4792b 100755 --- a/gnu/llvm/lldb/examples/python/gdbremote.py +++ b/gnu/llvm/lldb/examples/python/gdbremote.py @@ -16,7 +16,6 @@ # available. #---------------------------------------------------------------------- -from __future__ import print_function import binascii import subprocess import json @@ -260,6 +259,12 @@ def stop_gdb_log(debugger, command, result, dict): dest='verbose', help='display verbose debug info', default=False) + parser.add_option( + '--plot', + action='store_true', + dest='plot', + help='plot packet latencies by packet type', + default=False) parser.add_option( '-q', '--quiet', @@ -556,11 +561,11 @@ class Packet: return kvp def split(self, ch): - return string.split(self.str, ch) + return self.str.split(ch) def split_hex(self, ch, byte_order): hex_values = list() - strings = string.split(self.str, ch) + strings = self.str.split(ch) for str in strings: hex_values.append(Packet(str).get_hex_uint(byte_order)) return hex_values @@ -888,7 +893,7 @@ def rsp_vCont(options, cmd, cmd_args, rsp): def cmd_vAttach(options, cmd, args): - (extra_command, args) = string.split(args, ';') + (extra_command, args) = args.split(';') if extra_command: print("%s%s(%s)" % (cmd, extra_command, args)) else: @@ -1212,9 +1217,13 @@ def decode_packet(s, start_index=0): def rsp_json(options, cmd, cmd_args, rsp): print('%s() reply:' % (cmd)) - json_tree = json.loads(rsp) - print(json.dumps(json_tree, indent=4, separators=(',', ': '))) - + if not rsp: + return + try: + json_tree = json.loads(rsp) + print(json.dumps(json_tree, indent=4, separators=(',', ': '))) + except json.JSONDecodeError: + return def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp): if cmd_args: @@ -1541,7 +1550,7 @@ def parse_gdb_log(file, options): print(" %24s %11.6f %5.2f%% %6d %9.6f" % ( item, packet_total_time, packet_percent, packet_count, float(packet_total_time) / float(packet_count))) - if options.plot: + if options and options.plot: plot_latencies(packet_times) if __name__ == '__main__': @@ -1558,12 +1567,6 @@ if __name__ == '__main__': dest='verbose', help='display verbose debug info', default=False) - parser.add_option( - '--plot', - action='store_true', - dest='plot', - help='plot packet latencies by packet type', - default=False) parser.add_option( '-q', '--quiet', @@ -1619,13 +1622,11 @@ if __name__ == '__main__': else: parse_gdb_log(sys.stdin, options) -else: - import lldb - if lldb.debugger: - # This initializer is being run from LLDB in the embedded command interpreter - # Add any commands contained in this module to LLDB - lldb.debugger.HandleCommand( - 'command script add -f gdbremote.start_gdb_log start_gdb_log') - lldb.debugger.HandleCommand( - 'command script add -f gdbremote.stop_gdb_log stop_gdb_log') - print('The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information') +def __lldb_init_module(debugger, internal_dict): + # This initializer is being run from LLDB in the embedded command interpreter + # Add any commands contained in this module to LLDB + debugger.HandleCommand( + 'command script add -o -f gdbremote.start_gdb_log start_gdb_log') + debugger.HandleCommand( + 'command script add -o -f gdbremote.stop_gdb_log stop_gdb_log') + print('The "start_gdb_log" and "stop_gdb_log" commands are now installed and ready for use, type "start_gdb_log --help" or "stop_gdb_log --help" for more information') diff --git a/gnu/llvm/lldb/examples/python/globals.py b/gnu/llvm/lldb/examples/python/globals.py index 96645afef00..3d6cc9b0171 100755 --- a/gnu/llvm/lldb/examples/python/globals.py +++ b/gnu/llvm/lldb/examples/python/globals.py @@ -7,7 +7,6 @@ # For the shells sh, bash: # PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python ./globals.py [ ...] #---------------------------------------------------------------------- -from __future__ import print_function import lldb import optparse diff --git a/gnu/llvm/lldb/examples/python/in_call_stack.py b/gnu/llvm/lldb/examples/python/in_call_stack.py index 0647f2ca342..9fd32c0e211 100755 --- a/gnu/llvm/lldb/examples/python/in_call_stack.py +++ b/gnu/llvm/lldb/examples/python/in_call_stack.py @@ -3,7 +3,7 @@ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand( - 'command alias in_call_stack breakpoint command add --python-function in_call_stack.in_call_stack -k name -v %1' + f'command alias in_call_stack breakpoint command add --python-function {__name__}.in_call_stack -k name -v %1' ) diff --git a/gnu/llvm/lldb/examples/python/jump.py b/gnu/llvm/lldb/examples/python/jump.py index dc4cc48b144..0dc65153810 100644 --- a/gnu/llvm/lldb/examples/python/jump.py +++ b/gnu/llvm/lldb/examples/python/jump.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import lldb import re @@ -191,8 +189,8 @@ def jump(debugger, command, result, internal_dict): frame.SetPC(desired_address.GetLoadAddress(target)) -if lldb.debugger: +def __lldb_init_module(debugger, internal_dict): # Module is being run inside the LLDB interpreter jump.__doc__ = usage_string() - lldb.debugger.HandleCommand('command script add -f jump.jump jump') + debugger.HandleCommand('command script add -o -f jump.jump jump') print('The "jump" command has been installed, type "help jump" or "jump " for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/lldb_module_utils.py b/gnu/llvm/lldb/examples/python/lldb_module_utils.py index c0ac5751ce2..9a9b92b6065 100644 --- a/gnu/llvm/lldb/examples/python/lldb_module_utils.py +++ b/gnu/llvm/lldb/examples/python/lldb_module_utils.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import lldb import optparse @@ -10,7 +9,7 @@ import sys class DumpLineTables: command_name = "dump-line-tables" - short_decription = "Dumps full paths to compile unit files and optionally all line table files." + short_description = "Dumps full paths to compile unit files and optionally all line table files." description = 'Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.' usage = "usage: %prog [options] MODULE1 [MODULE2 ...]" def create_options(self): @@ -28,7 +27,7 @@ class DumpLineTables: default=False) def get_short_help(self): - return self.short_decription + return self.short_description def get_long_help(self): return self.help_string @@ -184,9 +183,9 @@ def __lldb_init_module(debugger, dict): # Add any commands contained in this module to LLDB debugger.HandleCommand( - 'command script add -c %s.DumpLineTables %s' % (__name__, + 'command script add -o -c %s.DumpLineTables %s' % (__name__, DumpLineTables.command_name)) debugger.HandleCommand( - 'command script add -c %s.DumpFiles %s' % (__name__, DumpFiles.command_name)) + 'command script add -o -c %s.DumpFiles %s' % (__name__, DumpFiles.command_name)) print('The "%s" and "%s" commands have been installed.' % (DumpLineTables.command_name, DumpFiles.command_name)) diff --git a/gnu/llvm/lldb/examples/python/lldbtk.py b/gnu/llvm/lldb/examples/python/lldbtk.py index a6a420ba1bd..55633df3dad 100644 --- a/gnu/llvm/lldb/examples/python/lldbtk.py +++ b/gnu/llvm/lldb/examples/python/lldbtk.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import lldb import shlex diff --git a/gnu/llvm/lldb/examples/python/mach_o.py b/gnu/llvm/lldb/examples/python/mach_o.py index 03ab73b3be9..d9e1841363b 100755 --- a/gnu/llvm/lldb/examples/python/mach_o.py +++ b/gnu/llvm/lldb/examples/python/mach_o.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import cmd import dict_utils diff --git a/gnu/llvm/lldb/examples/python/memory.py b/gnu/llvm/lldb/examples/python/memory.py index 26703462c2c..ffa0bb410db 100755 --- a/gnu/llvm/lldb/examples/python/memory.py +++ b/gnu/llvm/lldb/examples/python/memory.py @@ -9,8 +9,6 @@ # (lldb) command script import /path/to/cmdtemplate.py #---------------------------------------------------------------------- -from __future__ import print_function - import platform import os import re @@ -270,8 +268,9 @@ def memfind(target, options, args, result): if __name__ == '__main__': print('error: this script is designed to be used within the embedded script interpreter in LLDB') -elif getattr(lldb, 'debugger', None): + +def __lldb_init_module(debugger, internal_dict): memfind_command.__doc__ = create_memfind_options().format_help() - lldb.debugger.HandleCommand( - 'command script add -f memory.memfind_command memfind') + debugger.HandleCommand( + 'command script add -o -f memory.memfind_command memfind') print('"memfind" command installed, use the "--help" option for detailed help') diff --git a/gnu/llvm/lldb/examples/python/performance.py b/gnu/llvm/lldb/examples/python/performance.py index 57e9d1e0a24..cfba73e5083 100755 --- a/gnu/llvm/lldb/examples/python/performance.py +++ b/gnu/llvm/lldb/examples/python/performance.py @@ -8,8 +8,6 @@ # export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python #---------------------------------------------------------------------- -from __future__ import print_function - import optparse import os import platform diff --git a/gnu/llvm/lldb/examples/python/process_events.py b/gnu/llvm/lldb/examples/python/process_events.py index cb4bf788119..16706d81b33 100755 --- a/gnu/llvm/lldb/examples/python/process_events.py +++ b/gnu/llvm/lldb/examples/python/process_events.py @@ -8,8 +8,6 @@ # export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python #---------------------------------------------------------------------- -from __future__ import print_function - import optparse import os import platform diff --git a/gnu/llvm/lldb/examples/python/pytracer.py b/gnu/llvm/lldb/examples/python/pytracer.py index 27f88d7a3ee..561b90f4a7e 100644 --- a/gnu/llvm/lldb/examples/python/pytracer.py +++ b/gnu/llvm/lldb/examples/python/pytracer.py @@ -1,4 +1,3 @@ -from __future__ import print_function import sys import inspect from collections import OrderedDict diff --git a/gnu/llvm/lldb/examples/python/scripted_process/crashlog_scripted_process.py b/gnu/llvm/lldb/examples/python/scripted_process/crashlog_scripted_process.py new file mode 100644 index 00000000000..dfb32aae6d3 --- /dev/null +++ b/gnu/llvm/lldb/examples/python/scripted_process/crashlog_scripted_process.py @@ -0,0 +1,211 @@ +import os,json,struct,signal,uuid + +from typing import Any, Dict + +import lldb +from lldb.plugins.scripted_process import ScriptedProcess +from lldb.plugins.scripted_process import ScriptedThread + +from lldb.macosx.crashlog import CrashLog,CrashLogParser + +class CrashLogScriptedProcess(ScriptedProcess): + def parse_crashlog(self): + crashlog_parser = CrashLogParser.create(self.dbg, self.crashlog_path, False) + crash_log = crashlog_parser.parse() + + self.pid = crash_log.process_id + self.addr_mask = crash_log.addr_mask + self.crashed_thread_idx = crash_log.crashed_thread_idx + self.loaded_images = [] + self.exception = crash_log.exception + self.app_specific_thread = None + if hasattr(crash_log, 'asi'): + self.metadata['asi'] = crash_log.asi + if hasattr(crash_log, 'asb'): + self.extended_thread_info = crash_log.asb + + def load_images(self, images): + #TODO: Add to self.loaded_images and load images in lldb + if images: + for image in images: + if image not in self.loaded_images: + if image.uuid == uuid.UUID(int=0): + continue + err = image.add_module(self.target) + if err: + # Append to SBCommandReturnObject + print(err) + else: + self.loaded_images.append(image) + + for thread in crash_log.threads: + if self.load_all_images: + load_images(self, crash_log.images) + elif thread.did_crash(): + for ident in thread.idents: + load_images(self, crash_log.find_images_with_identifier(ident)) + + if hasattr(thread, 'app_specific_backtrace') and thread.app_specific_backtrace: + # We don't want to include the Application Specific Backtrace + # Thread into the Scripted Process' Thread list. + # Instead, we will try to extract the stackframe pcs from the + # backtrace and inject that as the extended thread info. + self.app_specific_thread = thread + continue + + self.threads[thread.index] = CrashLogScriptedThread(self, None, thread) + + + if self.app_specific_thread: + self.extended_thread_info = \ + CrashLogScriptedThread.resolve_stackframes(self.app_specific_thread, + self.addr_mask, + self.target) + + def __init__(self, exe_ctx: lldb.SBExecutionContext, args : lldb.SBStructuredData): + super().__init__(exe_ctx, args) + + if not self.target or not self.target.IsValid(): + # Return error + return + + self.crashlog_path = None + + crashlog_path = args.GetValueForKey("file_path") + if crashlog_path and crashlog_path.IsValid(): + if crashlog_path.GetType() == lldb.eStructuredDataTypeString: + self.crashlog_path = crashlog_path.GetStringValue(4096) + + if not self.crashlog_path: + # Return error + return + + load_all_images = args.GetValueForKey("load_all_images") + if load_all_images and load_all_images.IsValid(): + if load_all_images.GetType() == lldb.eStructuredDataTypeBoolean: + self.load_all_images = load_all_images.GetBooleanValue() + + if not self.load_all_images: + self.load_all_images = False + + self.pid = super().get_process_id() + self.crashed_thread_idx = 0 + self.exception = None + self.extended_thread_info = None + self.parse_crashlog() + + def get_memory_region_containing_address(self, addr: int) -> lldb.SBMemoryRegionInfo: + return None + + def get_thread_with_id(self, tid: int): + return {} + + def get_registers_for_thread(self, tid: int): + return {} + + def read_memory_at_address(self, addr: int, size: int, error: lldb.SBError) -> lldb.SBData: + # NOTE: CrashLogs don't contain any memory. + return lldb.SBData() + + def get_loaded_images(self): + # TODO: Iterate over corefile_target modules and build a data structure + # from it. + return self.loaded_images + + def get_process_id(self) -> int: + return self.pid + + def should_stop(self) -> bool: + return True + + def is_alive(self) -> bool: + return True + + def get_scripted_thread_plugin(self): + return CrashLogScriptedThread.__module__ + "." + CrashLogScriptedThread.__name__ + + def get_process_metadata(self): + return self.metadata + +class CrashLogScriptedThread(ScriptedThread): + def create_register_ctx(self): + if not self.has_crashed: + return dict.fromkeys([*map(lambda reg: reg['name'], self.register_info['registers'])] , 0) + + if not self.backing_thread or not len(self.backing_thread.registers): + return dict.fromkeys([*map(lambda reg: reg['name'], self.register_info['registers'])] , 0) + + for reg in self.register_info['registers']: + reg_name = reg['name'] + if reg_name in self.backing_thread.registers: + self.register_ctx[reg_name] = self.backing_thread.registers[reg_name] + else: + self.register_ctx[reg_name] = 0 + + return self.register_ctx + + def resolve_stackframes(thread, addr_mask, target): + frames = [] + for frame in thread.frames: + frame_pc = frame.pc & addr_mask + pc = frame_pc if frame.index == 0 or frame_pc == 0 else frame_pc - 1 + sym_addr = lldb.SBAddress() + sym_addr.SetLoadAddress(pc, target) + if not sym_addr.IsValid(): + continue + frames.append({"idx": frame.index, "pc": pc}) + return frames + + + def create_stackframes(self): + if not (self.scripted_process.load_all_images or self.has_crashed): + return None + + if not self.backing_thread or not len(self.backing_thread.frames): + return None + + self.frames = CrashLogScriptedThread.resolve_stackframes(self.backing_thread, + self.scripted_process.addr_mask, + self.target) + + return self.frames + + def __init__(self, process, args, crashlog_thread): + super().__init__(process, args) + + self.backing_thread = crashlog_thread + self.idx = self.backing_thread.index + self.tid = self.backing_thread.id + if self.backing_thread.app_specific_backtrace: + self.name = "Application Specific Backtrace - " + str(self.idx) + else: + self.name = self.backing_thread.name + self.queue = self.backing_thread.queue + self.has_crashed = (self.scripted_process.crashed_thread_idx == self.idx) + self.create_stackframes() + + def get_state(self): + if not self.has_crashed: + return lldb.eStateStopped + return lldb.eStateCrashed + + def get_stop_reason(self) -> Dict[str, Any]: + if not self.has_crashed: + return { "type": lldb.eStopReasonNone } + # TODO: Investigate what stop reason should be reported when crashed + stop_reason = { "type": lldb.eStopReasonException, "data": { }} + if self.scripted_process.exception: + stop_reason['data']['mach_exception'] = self.scripted_process.exception + return stop_reason + + def get_register_context(self) -> str: + if not self.register_ctx: + self.register_ctx = self.create_register_ctx() + + return struct.pack("{}Q".format(len(self.register_ctx)), *self.register_ctx.values()) + + def get_extended_info(self): + if (self.has_crashed): + self.extended_info = self.scripted_process.extended_thread_info + return self.extended_info + diff --git a/gnu/llvm/lldb/examples/python/scripted_process/scripted_platform.py b/gnu/llvm/lldb/examples/python/scripted_process/scripted_platform.py new file mode 100644 index 00000000000..95b97911fc1 --- /dev/null +++ b/gnu/llvm/lldb/examples/python/scripted_process/scripted_platform.py @@ -0,0 +1,96 @@ +from abc import ABCMeta, abstractmethod + +import lldb + +class ScriptedPlatform(metaclass=ABCMeta): + + """ + The base class for a scripted platform. + + Most of the base class methods are `@abstractmethod` that need to be + overwritten by the inheriting class. + + DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE. + THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. + """ + + processes = None + + @abstractmethod + def __init__(self, exe_ctx, args): + """ Construct a scripted platform. + + Args: + exe_ctx (lldb.SBExecutionContext): The execution context for the scripted platform + args (lldb.SBStructuredData): A Dictionary holding arbitrary + key/value pairs used by the scripted platform. + """ + processes = [] + + @abstractmethod + def list_processes(self): + """ Get a list of processes that are running or that can be attached to on the platform. + + processes = { + 420: { + name: a.out, + arch: aarch64, + pid: 420, + parent_pid: 42 (optional), + uid: 0 (optional), + gid: 0 (optional), + }, + } + + Returns: + Dict: The processes represented as a dictionary, with at least the + process ID, name, architecture. Optionally, the user can also + provide the parent process ID and the user and group IDs. + The dictionary can be empty. + """ + pass + + def get_process_info(self, pid): + """ Get the dictionary describing the process. + + Returns: + Dict: The dictionary of process info that matched process ID. + None if the process doesn't exists + """ + pass + + @abstractmethod + def attach_to_process(self, attach_info): + """ Attach to a process. + + Args: + attach_info (lldb.SBAttachInfo): The information related to attach to a process. + + Returns: + lldb.SBError: A status object notifying if the attach succeeded. + """ + pass + + @abstractmethod + def launch_process(self, launch_info): + """ Launch a process. + + Args: + launch_info (lldb.SBLaunchInfo): The information related to the process launch. + + Returns: + lldb.SBError: A status object notifying if the launch succeeded. + """ + pass + + @abstractmethod + def kill_process(self, pid): + """ Kill a process. + + Args: + pid (int): Process ID for the process to be killed. + + Returns: + lldb.SBError: A status object notifying if the shutdown succeeded. + """ + pass diff --git a/gnu/llvm/lldb/examples/python/scripted_process/scripted_process.py b/gnu/llvm/lldb/examples/python/scripted_process/scripted_process.py index 72dce5c1e3b..a84e057edc5 100644 --- a/gnu/llvm/lldb/examples/python/scripted_process/scripted_process.py +++ b/gnu/llvm/lldb/examples/python/scripted_process/scripted_process.py @@ -1,10 +1,8 @@ from abc import ABCMeta, abstractmethod -import six import lldb -@six.add_metaclass(ABCMeta) -class ScriptedProcess: +class ScriptedProcess(metaclass=ABCMeta): """ The base class for a scripted process. @@ -16,24 +14,40 @@ class ScriptedProcess: THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. """ + memory_regions = None + loaded_images = None + threads = None + metadata = None + @abstractmethod - def __init__(self, target, args): + def __init__(self, exe_ctx, args): """ Construct a scripted process. Args: - target (lldb.SBTarget): The target launching the scripted process. + exe_ctx (lldb.SBExecutionContext): The execution context for the scripted process. args (lldb.SBStructuredData): A Dictionary holding arbitrary key/value pairs used by the scripted process. """ + target = None self.target = None self.args = None + self.arch = None + if isinstance(exe_ctx, lldb.SBExecutionContext): + target = exe_ctx.target if isinstance(target, lldb.SBTarget) and target.IsValid(): self.target = target + triple = self.target.triple + if triple: + self.arch = triple.split('-')[0] + self.dbg = target.GetDebugger() if isinstance(args, lldb.SBStructuredData) and args.IsValid(): self.args = args + self.threads = {} + self.loaded_images = [] + self.metadata = {} @abstractmethod - def get_memory_region_containing_address(addr): + def get_memory_region_containing_address(self, addr): """ Get the memory region for the scripted process, containing a specific address. @@ -47,22 +61,32 @@ class ScriptedProcess: """ pass + def get_threads_info(self): + """ Get the dictionary describing the process' Scripted Threads. + + Returns: + Dict: The dictionary of threads, with the thread ID as the key and + a Scripted Thread instance as the value. + The dictionary can be empty. + """ + return self.threads + @abstractmethod - def get_thread_with_id(tid): + def get_thread_with_id(self, tid): """ Get the scripted process thread with a specific ID. Args: tid (int): Thread ID to look for in the scripted process. Returns: - Dict: The thread represented as a dictionary, withr the + Dict: The thread represented as a dictionary, with the tid thread ID. None if tid doesn't match any of the scripted process threads. """ pass @abstractmethod - def get_registers_for_thread(tid): + def get_registers_for_thread(self, tid): """ Get the register context dictionary for a certain thread of the scripted process. @@ -77,13 +101,14 @@ class ScriptedProcess: pass @abstractmethod - def read_memory_at_address(addr, size): + def read_memory_at_address(self, addr, size, error): """ Get a memory buffer from the scripted process at a certain address, of a certain size. Args: addr (int): Address from which we should start reading. size (int): Size of the memory to read. + error (lldb.SBError): Error object. Returns: lldb.SBData: An `lldb.SBData` buffer with the target byte size and @@ -91,26 +116,24 @@ class ScriptedProcess: """ pass - @abstractmethod def get_loaded_images(self): """ Get the list of loaded images for the scripted process. ``` - class ScriptedProcessImage: - def __init__(name, file_spec, uuid, load_address): - self.name = name - self.file_spec = file_spec - self.uuid = uuid - self.load_address = load_address + scripted_image = { + uuid = "c6ea2b64-f77c-3d27-9528-74f507b9078b", + path = "/usr/lib/dyld" + load_addr = 0xbadc0ffee + } ``` Returns: - List[ScriptedProcessImage]: A list of `ScriptedProcessImage` - containing for each entry, the name of the library, a UUID, - an `lldb.SBFileSpec` and a load address. + List[scripted_image]: A list of `scripted_image` dictionaries + containing for each entry the library UUID or its file path + and its load address. None if the list is empty. """ - pass + return self.loaded_images def get_process_id(self): """ Get the scripted process identifier. @@ -120,7 +143,6 @@ class ScriptedProcess: """ return 0 - def launch(self): """ Simulate the scripted process launch. @@ -163,3 +185,232 @@ class ScriptedProcess: bool: True if scripted process is alive. False otherwise. """ pass + + @abstractmethod + def get_scripted_thread_plugin(self): + """ Get scripted thread plugin name. + + Returns: + str: Name of the scripted thread plugin. + """ + return None + + def get_process_metadata(self): + """ Get some metadata for the scripted process. + + Returns: + Dict: A dictionary containing metadata for the scripted process. + None is the process as no metadata. + """ + return self.metadata + +class ScriptedThread(metaclass=ABCMeta): + + """ + The base class for a scripted thread. + + Most of the base class methods are `@abstractmethod` that need to be + overwritten by the inheriting class. + + DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE. + THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE. + """ + + @abstractmethod + def __init__(self, scripted_process, args): + """ Construct a scripted thread. + + Args: + process (ScriptedProcess): The scripted process owning this thread. + args (lldb.SBStructuredData): A Dictionary holding arbitrary + key/value pairs used by the scripted thread. + """ + self.target = None + self.scripted_process = None + self.process = None + self.args = None + self.idx = 0 + self.tid = 0 + self.idx = None + self.name = None + self.queue = None + self.state = None + self.stop_reason = None + self.register_info = None + self.register_ctx = {} + self.frames = [] + self.extended_info = [] + + if isinstance(scripted_process, ScriptedProcess): + self.target = scripted_process.target + self.scripted_process = scripted_process + self.process = self.target.GetProcess() + self.get_register_info() + + def get_thread_idx(self): + """ Get the scripted thread index. + + Returns: + int: The index of the scripted thread in the scripted process. + """ + return self.idx + + def get_thread_id(self): + """ Get the scripted thread identifier. + + Returns: + int: The identifier of the scripted thread. + """ + return self.tid + + def get_name(self): + """ Get the scripted thread name. + + Returns: + str: The name of the scripted thread. + """ + return self.name + + def get_state(self): + """ Get the scripted thread state type. + + eStateStopped, ///< Process or thread is stopped and can be examined. + eStateRunning, ///< Process or thread is running and can't be examined. + eStateStepping, ///< Process or thread is in the process of stepping and can + /// not be examined. + eStateCrashed, ///< Process or thread has crashed and can be examined. + + Returns: + int: The state type of the scripted thread. + Returns lldb.eStateStopped by default. + """ + return lldb.eStateStopped + + def get_queue(self): + """ Get the scripted thread associated queue name. + This method is optional. + + Returns: + str: The queue name associated with the scripted thread. + """ + return self.queue + + @abstractmethod + def get_stop_reason(self): + """ Get the dictionary describing the stop reason type with some data. + This method is optional. + + Returns: + Dict: The dictionary holding the stop reason type and the possibly + the stop reason data. + """ + pass + + def get_stackframes(self): + """ Get the list of stack frames for the scripted thread. + + ``` + scripted_frame = { + idx = 0, + pc = 0xbadc0ffee + } + ``` + + Returns: + List[scripted_frame]: A list of `scripted_frame` dictionaries + containing at least for each entry, the frame index and + the program counter value for that frame. + The list can be empty. + """ + return self.frames + + def get_register_info(self): + if self.register_info is None: + self.register_info = dict() + if self.scripted_process.arch == 'x86_64': + self.register_info['sets'] = ['General Purpose Registers'] + self.register_info['registers'] = INTEL64_GPR + elif 'arm64' in self.scripted_process.arch: + self.register_info['sets'] = ['General Purpose Registers'] + self.register_info['registers'] = ARM64_GPR + else: raise ValueError('Unknown architecture', self.scripted_process.arch) + return self.register_info + + @abstractmethod + def get_register_context(self): + """ Get the scripted thread register context + + Returns: + str: A byte representing all register's value. + """ + pass + + def get_extended_info(self): + """ Get scripted thread extended information. + + Returns: + List: A list containing the extended information for the scripted process. + None is the thread as no extended information. + """ + return self.extended_info + +ARM64_GPR = [ {'name': 'x0', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0, 'generic': 'arg0', 'alt-name': 'arg0'}, + {'name': 'x1', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg1', 'alt-name': 'arg1'}, + {'name': 'x2', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg2', 'alt-name': 'arg2'}, + {'name': 'x3', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3, 'generic': 'arg3', 'alt-name': 'arg3'}, + {'name': 'x4', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg4', 'alt-name': 'arg4'}, + {'name': 'x5', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg5', 'alt-name': 'arg5'}, + {'name': 'x6', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'arg6', 'alt-name': 'arg6'}, + {'name': 'x7', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'arg7', 'alt-name': 'arg7'}, + {'name': 'x8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8 }, + {'name': 'x9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9 }, + {'name': 'x10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, + {'name': 'x11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, + {'name': 'x12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, + {'name': 'x13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, + {'name': 'x14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, + {'name': 'x15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, + {'name': 'x16', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16}, + {'name': 'x17', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 17, 'dwarf': 17}, + {'name': 'x18', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 18, 'dwarf': 18}, + {'name': 'x19', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 19, 'dwarf': 19}, + {'name': 'x20', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 20, 'dwarf': 20}, + {'name': 'x21', 'bitsize': 64, 'offset': 168, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 21, 'dwarf': 21}, + {'name': 'x22', 'bitsize': 64, 'offset': 176, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 22, 'dwarf': 22}, + {'name': 'x23', 'bitsize': 64, 'offset': 184, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 23, 'dwarf': 23}, + {'name': 'x24', 'bitsize': 64, 'offset': 192, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 24, 'dwarf': 24}, + {'name': 'x25', 'bitsize': 64, 'offset': 200, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 25, 'dwarf': 25}, + {'name': 'x26', 'bitsize': 64, 'offset': 208, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 26, 'dwarf': 26}, + {'name': 'x27', 'bitsize': 64, 'offset': 216, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 27, 'dwarf': 27}, + {'name': 'x28', 'bitsize': 64, 'offset': 224, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 28, 'dwarf': 28}, + {'name': 'x29', 'bitsize': 64, 'offset': 232, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 29, 'dwarf': 29, 'generic': 'fp', 'alt-name': 'fp'}, + {'name': 'x30', 'bitsize': 64, 'offset': 240, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 30, 'dwarf': 30, 'generic': 'lr', 'alt-name': 'lr'}, + {'name': 'sp', 'bitsize': 64, 'offset': 248, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 31, 'dwarf': 31, 'generic': 'sp', 'alt-name': 'sp'}, + {'name': 'pc', 'bitsize': 64, 'offset': 256, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 32, 'dwarf': 32, 'generic': 'pc', 'alt-name': 'pc'}, + {'name': 'cpsr', 'bitsize': 32, 'offset': 264, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 33, 'dwarf': 33} + ] + +INTEL64_GPR = [ {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0}, + {'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3}, + {'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4'}, + {'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3'}, + {'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1'}, + {'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2'}, + {'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp'}, + {'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp'}, + {'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5'}, + {'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6'}, + {'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10}, + {'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11}, + {'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12}, + {'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13}, + {'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14}, + {'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15}, + {'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'}, + {'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'}, + {'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0}, + {'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0} + ] + + diff --git a/gnu/llvm/lldb/examples/python/scripted_step.py b/gnu/llvm/lldb/examples/python/scripted_step.py index 3c1d5d7a6c4..011e24d70cb 100644 --- a/gnu/llvm/lldb/examples/python/scripted_step.py +++ b/gnu/llvm/lldb/examples/python/scripted_step.py @@ -93,8 +93,6 @@ # # (lldb) thread step-scripted -C scripted_step.StepWithPlan -from __future__ import print_function - import lldb diff --git a/gnu/llvm/lldb/examples/python/shadow.py b/gnu/llvm/lldb/examples/python/shadow.py index 73534dce535..1ad0288dd2e 100644 --- a/gnu/llvm/lldb/examples/python/shadow.py +++ b/gnu/llvm/lldb/examples/python/shadow.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import lldb import shlex diff --git a/gnu/llvm/lldb/examples/python/sources.py b/gnu/llvm/lldb/examples/python/sources.py index 38b3926768b..4fbfea48e15 100644 --- a/gnu/llvm/lldb/examples/python/sources.py +++ b/gnu/llvm/lldb/examples/python/sources.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import lldb import shlex @@ -28,5 +27,5 @@ def info_sources(debugger, command, result, dict): def __lldb_init_module(debugger, dict): # Add any commands contained in this module to LLDB debugger.HandleCommand( - 'command script add -f sources.info_sources info_sources') + 'command script add -o -f sources.info_sources info_sources') print('The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.') diff --git a/gnu/llvm/lldb/examples/python/stacks.py b/gnu/llvm/lldb/examples/python/stacks.py index 41729ec6744..6bcf2547c3e 100755 --- a/gnu/llvm/lldb/examples/python/stacks.py +++ b/gnu/llvm/lldb/examples/python/stacks.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -from __future__ import print_function import lldb import optparse import shlex @@ -63,6 +62,7 @@ def stack_frames(debugger, command, result, dict): print(frame_info) -lldb.debugger.HandleCommand( - "command script add -f stacks.stack_frames stack_frames") -print("A new command called 'stack_frames' was added, type 'stack_frames --help' for more information.") +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand( + "command script add -o -f stacks.stack_frames stack_frames") + print("A new command called 'stack_frames' was added, type 'stack_frames --help' for more information.") diff --git a/gnu/llvm/lldb/examples/python/step_and_print.py b/gnu/llvm/lldb/examples/python/step_and_print.py index 41364ef97ba..62a612eac18 100644 --- a/gnu/llvm/lldb/examples/python/step_and_print.py +++ b/gnu/llvm/lldb/examples/python/step_and_print.py @@ -21,4 +21,4 @@ class StepAndPrint: return "Does a step-over then runs frame variable passing the command args to it\n" def __lldb_init_module(debugger, unused): - debugger.HandleCommand("command script add -c step_and_print.StepAndPrint sap") + debugger.HandleCommand("command script add -o -c step_and_print.StepAndPrint sap") diff --git a/gnu/llvm/lldb/examples/python/symbolication.py b/gnu/llvm/lldb/examples/python/symbolication.py index 70f2ff3bb27..c722b73faa0 100755 --- a/gnu/llvm/lldb/examples/python/symbolication.py +++ b/gnu/llvm/lldb/examples/python/symbolication.py @@ -26,7 +26,6 @@ # PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash #---------------------------------------------------------------------- -from __future__ import print_function import lldb import optparse import os @@ -379,7 +378,7 @@ class Image: return None resolved_path = self.get_resolved_path() self.module = target.AddModule( - resolved_path, str(self.arch), uuid_str, self.symfile) + resolved_path, None, uuid_str, self.symfile) if not self.module: return 'error: unable to get module for (%s) "%s"' % ( self.arch, self.get_resolved_path()) diff --git a/gnu/llvm/lldb/examples/python/types.py b/gnu/llvm/lldb/examples/python/types.py index 513a03b2600..6110d110713 100755 --- a/gnu/llvm/lldb/examples/python/types.py +++ b/gnu/llvm/lldb/examples/python/types.py @@ -9,8 +9,6 @@ # (lldb) command script import /path/to/cmdtemplate.py #---------------------------------------------------------------------- -from __future__ import print_function - import platform import os import re @@ -351,7 +349,7 @@ if __name__ == '__main__': continue verify_types(target, options) -elif getattr(lldb, 'debugger', None): - lldb.debugger.HandleCommand( - 'command script add -f types.check_padding_command check_padding') +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand( + 'command script add -o -f types.check_padding_command check_padding') print('"check_padding" command installed, use the "--help" option for detailed help') diff --git a/gnu/llvm/lldb/examples/scripting/tree_utils.py b/gnu/llvm/lldb/examples/scripting/tree_utils.py index e99f7c63bed..69b5406457c 100755 --- a/gnu/llvm/lldb/examples/scripting/tree_utils.py +++ b/gnu/llvm/lldb/examples/scripting/tree_utils.py @@ -18,8 +18,6 @@ for more information about dictionary.c go to http://lldb.llvm.org/scripting.html """ -from __future__ import print_function - def DFS(root, word, cur_path): """ diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/CFArray.py b/gnu/llvm/lldb/examples/summaries/cocoa/CFArray.py index baf1ca30ce0..e3916011bd8 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/CFArray.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/CFArray.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -222,7 +217,7 @@ def CFArray_SummaryProvider(valobj, dict): logger >> "provider gave me " + str(summary) if summary is None: summary = '' - elif isinstance(summary, basestring): + elif isinstance(summary, str): pass else: # we format it like it were a CFString to make it look the same as diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/CFBag.py b/gnu/llvm/lldb/examples/summaries/cocoa/CFBag.py index 55c3fe6b68f..6a75b0222ab 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/CFBag.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/CFBag.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -150,7 +145,7 @@ def CFBag_SummaryProvider(valobj, dict): # the mask needs to be changed) if summary is None: summary = '' - elif isinstance(summary, basestring): + elif isinstance(summary, str): pass else: if provider.sys_params.is_64_bit: diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py b/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py index 061ab61ae4c..f22a044b681 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -148,7 +143,7 @@ def CFBinaryHeap_SummaryProvider(valobj, dict): # the mask needs to be changed) if summary is None: summary = '' - elif isinstance(summary, basestring): + elif isinstance(summary, str): pass else: if provider.sys_params.is_64_bit: diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/CFBitVector.py b/gnu/llvm/lldb/examples/summaries/cocoa/CFBitVector.py index 73552a3e2b8..7ee5fc2cdbf 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/CFBitVector.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/CFBitVector.py @@ -5,7 +5,6 @@ Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. See https://llvm.org/LICENSE.txt for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception """ -from __future__ import print_function # summary provider for CF(Mutable)BitVector import lldb diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/CFDictionary.py b/gnu/llvm/lldb/examples/summaries/cocoa/CFDictionary.py index 6fcc0a6fe77..fa132605cb1 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/CFDictionary.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/CFDictionary.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -227,7 +222,7 @@ def CFDictionary_SummaryProvider(valobj, dict): logger >> "got summary " + str(summary) if summary is None: return '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summary return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair") @@ -249,7 +244,7 @@ def CFDictionary_SummaryProvider2(valobj, dict): logger >> "got summary " + str(summary) if summary is None: summary = '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summary else: # needed on OSX Mountain Lion diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/Logger.py b/gnu/llvm/lldb/examples/summaries/cocoa/Logger.py index e518b75b20c..e051a82e4bc 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/Logger.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/Logger.py @@ -1,4 +1,3 @@ -from __future__ import print_function import sys import os.path import inspect diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/NSData.py b/gnu/llvm/lldb/examples/summaries/cocoa/NSData.py index 005a1cac50c..d6edabbc231 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/NSData.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/NSData.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -141,7 +136,7 @@ def NSData_SummaryProvider(valobj, dict): logger >> "got a summary: it is " + str(summary) if summary is None: summary = '' - elif isinstance(summary, basestring): + elif isinstance(summary, str): pass else: if summary == 1: @@ -169,7 +164,7 @@ def NSData_SummaryProvider2(valobj, dict): logger >> "got a summary: it is " + str(summary) if summary is None: summary = '' - elif isinstance(summary, basestring): + elif isinstance(summary, str): pass else: if summary == 1: diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/NSIndexSet.py b/gnu/llvm/lldb/examples/summaries/cocoa/NSIndexSet.py index 25588350c11..5ec54954532 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/NSIndexSet.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/NSIndexSet.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -168,7 +163,7 @@ def NSIndexSet_SummaryProvider(valobj, dict): logger >> "got summary " + str(summary) if summary is None: summary = '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summary else: summary = str(summary) + (' indexes' if summary != 1 else ' index') diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/NSMachPort.py b/gnu/llvm/lldb/examples/summaries/cocoa/NSMachPort.py index 624b34350de..25488138dfc 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/NSMachPort.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/NSMachPort.py @@ -13,11 +13,6 @@ import lldb.runtime.objc.objc_runtime import lldb.formatters.metrics import lldb.formatters.Logger -try: - basestring -except NameError: - basestring =str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -135,7 +130,7 @@ def NSMachPort_SummaryProvider(valobj, dict): logger >> "got summary " + str(summary) if summary is None: summary = '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summay return 'mach port: ' + str(summary) return 'Summary Unavailable' diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/NSNumber.py b/gnu/llvm/lldb/examples/summaries/cocoa/NSNumber.py index 7132e34d170..983222b880c 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/NSNumber.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/NSNumber.py @@ -8,8 +8,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # example summary provider for NSNumber # the real summary is now C++ code built into LLDB -from __future__ import print_function - import lldb import ctypes import lldb.runtime.objc.objc_runtime diff --git a/gnu/llvm/lldb/examples/summaries/cocoa/NSSet.py b/gnu/llvm/lldb/examples/summaries/cocoa/NSSet.py index 27cdd302c34..e3a6a1de896 100644 --- a/gnu/llvm/lldb/examples/summaries/cocoa/NSSet.py +++ b/gnu/llvm/lldb/examples/summaries/cocoa/NSSet.py @@ -13,11 +13,6 @@ import lldb.formatters.metrics import CFBag import lldb.formatters.Logger -try: - basestring -except NameError: - basestring = str - statistics = lldb.formatters.metrics.Metrics() statistics.add_metric('invalid_isa') statistics.add_metric('invalid_pointer') @@ -247,7 +242,7 @@ def NSSet_SummaryProvider(valobj, dict): summary = None if summary is None: summary = '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summary else: summary = str(summary) + \ @@ -276,7 +271,7 @@ def NSSet_SummaryProvider2(valobj, dict): # the mask needs to be changed) if summary is None: summary = '' - if isinstance(summary, basestring): + if isinstance(summary, str): return summary else: if provider.sys_params.is_64_bit: diff --git a/gnu/llvm/lldb/examples/summaries/synth.py b/gnu/llvm/lldb/examples/summaries/synth.py index 02dcc4f7014..97e84ea9b09 100644 --- a/gnu/llvm/lldb/examples/summaries/synth.py +++ b/gnu/llvm/lldb/examples/summaries/synth.py @@ -33,8 +33,7 @@ class PythonObjectSyntheticChildProvider(object): def gen_child(self, name, value): data = None type = None - import six - if isinstance(value, six.integer_types): + if isinstance(value, int): data = lldb.SBData.CreateDataFromUInt64Array( self.bo, self.ps, [value]) type = self.value.target.GetBasicType(lldb.eBasicTypeLong) diff --git a/gnu/llvm/lldb/examples/synthetic/gnu_libstdcpp.py b/gnu/llvm/lldb/examples/synthetic/gnu_libstdcpp.py index 528b28349bb..d1dd2d6c95b 100644 --- a/gnu/llvm/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/gnu/llvm/lldb/examples/synthetic/gnu_libstdcpp.py @@ -1,20 +1,145 @@ -from __future__ import division -import re import lldb.formatters.Logger # C++ STL formatters for LLDB -# These formatters are based upon the version of the GNU libstdc++ -# as it ships with Mac OS X 10.6.8 thru 10.8.0 -# You are encouraged to look at the STL implementation for your platform -# before relying on these formatters to do the right thing for your setup +# As there are many versions of the libstdc++, you are encouraged to look at the STL +# implementation for your platform before relying on these formatters to do the right +# thing for your setup +def ForwardListSummaryProvider(valobj, dict): + list_capping_size = valobj.GetTarget().GetMaximumNumberOfChildrenToDisplay() + text = "size=" + str(valobj.GetNumChildren()) + if valobj.GetNumChildren() > list_capping_size: + return "(capped) " + text + else: + return text -class StdListSynthProvider: +def StdOptionalSummaryProvider(valobj, dict): + has_value = valobj.GetNumChildren() > 0 + # We add wrapping spaces for consistency with the libcxx formatter + return " Has Value=" + ("true" if has_value else "false") + " " + +class StdOptionalSynthProvider: def __init__(self, valobj, dict): + self.valobj = valobj + + def update(self): + try: + self.payload = self.valobj.GetChildMemberWithName('_M_payload') + self.value = self.payload.GetChildMemberWithName('_M_payload') + self.has_value = self.payload.GetChildMemberWithName('_M_engaged').GetValueAsUnsigned(0) != 0 + except: + self.has_value = False + return False + + + def num_children(self): + return 1 if self.has_value else 0 + + def get_child_index(self, name): + return 0 + + def get_child_at_index(self, index): + # some versions of libstdcpp have an additional _M_value child with the actual value + possible_value = self.value.GetChildMemberWithName('_M_value') + if possible_value.IsValid(): + return possible_value.Clone('Value') + return self.value.Clone('Value') + +""" + This formatter can be applied to all + unordered map-like structures (unordered_map, unordered_multimap, unordered_set, unordered_multiset) +""" +class StdUnorderedMapSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj + self.count = None + self.kind = self.get_object_kind(valobj) + + def get_object_kind(self, valobj): + type_name = valobj.GetTypeName() + return "set" if "set" in type_name else "map" + + def extract_type(self): + type = self.valobj.GetType() + # type of std::pair is the first template + # argument type of the 4th template argument to std::map and + # 3rd template argument for std::set. That's why + # we need to know kind of the object + template_arg_num = 4 if self.kind == "map" else 3 + allocator_type = type.GetTemplateArgumentType(template_arg_num) + data_type = allocator_type.GetTemplateArgumentType(0) + return data_type + + def update(self): + # preemptively setting this to None - we might end up changing our mind + # later + self.count = None + try: + self.head = self.valobj.GetChildMemberWithName('_M_h') + self.before_begin = self.head.GetChildMemberWithName('_M_before_begin') + self.next = self.before_begin.GetChildMemberWithName('_M_nxt') + self.data_type = self.extract_type() + self.skip_size = self.next.GetType().GetByteSize() + self.data_size = self.data_type.GetByteSize() + if (not self.data_type.IsValid()) or (not self.next.IsValid()): + self.count = 0 + except: + self.count = 0 + return False + + def get_child_index(self, name): + try: + return int(name.lstrip('[').rstrip(']')) + except: + return -1 + + def get_child_at_index(self, index): + logger = lldb.formatters.Logger.Logger() + logger >> "Being asked to fetch child[" + str(index) + "]" + if index < 0: + return None + if index >= self.num_children(): + return None + try: + offset = index + current = self.next + while offset > 0: + current = current.GetChildMemberWithName('_M_nxt') + offset = offset - 1 + return current.CreateChildAtOffset( '[' + str(index) + ']', self.skip_size, self.data_type) + + except: + logger >> "Cannot get child" + return None + + def num_children(self): + if self.count is None: + self.count = self.num_children_impl() + return self.count + + def num_children_impl(self): + logger = lldb.formatters.Logger.Logger() + try: + count = self.head.GetChildMemberWithName('_M_element_count').GetValueAsUnsigned(0) + return count + except: + logger >> "Could not determine the size" + return 0 + + +class AbstractListSynthProvider: + def __init__(self, valobj, dict, has_prev): + ''' + :param valobj: The value object of the list + :param dict: A dict with metadata provided by LLDB + :param has_prev: Whether the list supports a 'prev' pointer besides a 'next' one + ''' logger = lldb.formatters.Logger.Logger() self.valobj = valobj self.count = None + self.has_prev = has_prev + self.list_capping_size = self.valobj.GetTarget().GetMaximumNumberOfChildrenToDisplay() logger >> "Providing synthetic children for a list named " + \ str(valobj.GetName()) @@ -24,7 +149,7 @@ class StdListSynthProvider: def is_valid(self, node): logger = lldb.formatters.Logger.Logger() - valid = self.value(self.next_node(node)) != self.node_address + valid = self.value(self.next_node(node)) != self.get_end_of_list_address() if valid: logger >> "%s is valid" % str(self.valobj.GetName()) else: @@ -73,26 +198,35 @@ class StdListSynthProvider: def num_children_impl(self): logger = lldb.formatters.Logger.Logger() try: - next_val = self.next.GetValueAsUnsigned(0) - prev_val = self.prev.GetValueAsUnsigned(0) # After a std::list has been initialized, both next and prev will # be non-NULL - if next_val == 0 or prev_val == 0: - return 0 - if next_val == self.node_address: + next_val = self.next.GetValueAsUnsigned(0) + if next_val == 0: return 0 - if next_val == prev_val: - return 1 if self.has_loop(): return 0 - size = 2 + if self.has_prev: + prev_val = self.prev.GetValueAsUnsigned(0) + if prev_val == 0: + return 0 + if next_val == self.node_address: + return 0 + if next_val == prev_val: + return 1 + size = 1 current = self.next while current.GetChildMemberWithName( - '_M_next').GetValueAsUnsigned(0) != self.node_address: - size = size + 1 + '_M_next').GetValueAsUnsigned(0) != self.get_end_of_list_address(): current = current.GetChildMemberWithName('_M_next') - return (size - 1) + if not current.IsValid(): + break + size = size + 1 + if size >= self.list_capping_size: + break + + return size except: + logger >> "Error determining the size" return 0 def get_child_index(self, name): @@ -115,9 +249,11 @@ class StdListSynthProvider: while offset > 0: current = current.GetChildMemberWithName('_M_next') offset = offset - 1 + # C++ lists store the data of a node after its pointers. In the case of a forward list, there's just one pointer (next), and + # in the case of a double-linked list, there's an additional pointer (prev). return current.CreateChildAtOffset( '[' + str(index) + ']', - 2 * current.GetType().GetByteSize(), + (2 if self.has_prev else 1) * current.GetType().GetByteSize(), self.data_type) except: return None @@ -128,10 +264,8 @@ class StdListSynthProvider: if list_type.IsReferenceType(): list_type = list_type.GetDereferencedType() if list_type.GetNumberOfTemplateArguments() > 0: - data_type = list_type.GetTemplateArgumentType(0) - else: - data_type = None - return data_type + return list_type.GetTemplateArgumentType(0) + return lldb.SBType() def update(self): logger = lldb.formatters.Logger.Logger() @@ -139,20 +273,72 @@ class StdListSynthProvider: # later self.count = None try: - impl = self.valobj.GetChildMemberWithName('_M_impl') - self.node = impl.GetChildMemberWithName('_M_node') - self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0) - self.next = self.node.GetChildMemberWithName('_M_next') - self.prev = self.node.GetChildMemberWithName('_M_prev') + self.impl = self.valobj.GetChildMemberWithName('_M_impl') self.data_type = self.extract_type() - self.data_size = self.data_type.GetByteSize() + if (not self.data_type.IsValid()) or (not self.impl.IsValid()): + self.count = 0 + elif not self.updateNodes(): + self.count = 0 + else: + self.data_size = self.data_type.GetByteSize() except: - pass + self.count = 0 return False + ''' + Method is used to extract the list pointers into the variables (e.g self.node, self.next, and optionally to self.prev) + and is mandatory to be overriden in each AbstractListSynthProvider subclass. + This should return True or False depending on wheter it found valid data. + ''' + def updateNodes(self): + raise NotImplementedError + def has_children(self): return True + ''' + Method is used to identify if a node traversal has reached its end + and is mandatory to be overriden in each AbstractListSynthProvider subclass + ''' + def get_end_of_list_address(self): + raise NotImplementedError + + +class StdForwardListSynthProvider(AbstractListSynthProvider): + + def __init__(self, valobj, dict): + has_prev = False + super().__init__(valobj, dict, has_prev) + + def updateNodes(self): + self.node = self.impl.GetChildMemberWithName('_M_head') + self.next = self.node.GetChildMemberWithName('_M_next') + if (not self.node.IsValid()) or (not self.next.IsValid()): + return False + return True + + def get_end_of_list_address(self): + return 0 + + +class StdListSynthProvider(AbstractListSynthProvider): + + def __init__(self, valobj, dict): + has_prev = True + super().__init__(valobj, dict, has_prev) + + def updateNodes(self): + self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0) + self.node = self.impl.GetChildMemberWithName('_M_node') + self.prev = self.node.GetChildMemberWithName('_M_prev') + self.next = self.node.GetChildMemberWithName('_M_next') + if self.node_address == 0 or (not self.node.IsValid()) or (not self.next.IsValid()) or (not self.prev.IsValid()): + return False + return True + + def get_end_of_list_address(self): + return self.node_address + class StdVectorSynthProvider: @@ -235,8 +421,8 @@ class StdVectorSynthProvider: else: self.count = 0 except: - pass - return False + self.count = 0 + return False class StdVBoolImplementation(object): @@ -280,7 +466,10 @@ class StdVectorSynthProvider: self.start_p = self.m_start.GetChildMemberWithName('_M_p') self.finish_p = self.m_finish.GetChildMemberWithName('_M_p') self.offset = self.m_finish.GetChildMemberWithName('_M_offset') - self.valid = True + if self.offset.IsValid() and self.start_p.IsValid() and self.finish_p.IsValid(): + self.valid = True + else: + self.valid = False except: self.valid = False return False @@ -314,19 +503,30 @@ class StdVectorSynthProvider: def has_children(self): return True - -class StdMapSynthProvider: + """ + This formatter can be applied to all + map-like structures (map, multimap, set, multiset) + """ +class StdMapLikeSynthProvider: def __init__(self, valobj, dict): logger = lldb.formatters.Logger.Logger() self.valobj = valobj self.count = None - logger >> "Providing synthetic children for a map named " + \ + self.kind = self.get_object_kind(valobj) + logger >> "Providing synthetic children for a " + self.kind + " named " + \ str(valobj.GetName()) + def get_object_kind(self, valobj): + type_name = valobj.GetTypeName() + for kind in ["multiset", "multimap", "set", "map"]: + if kind in type_name: + return kind + return type_name + # we need this function as a temporary workaround for rdar://problem/10801549 # which prevents us from extracting the std::pair SBType out of the template - # arguments for _Rep_Type _M_t in the map itself - because we have to make up the + # arguments for _Rep_Type _M_t in the object itself - because we have to make up the # typename and then find it, we may hit the situation were std::string has multiple # names but only one is actually referenced in the debug information. hence, we need # to replace the longer versions of std::string with the shorter one in order to be able @@ -349,36 +549,38 @@ class StdMapSynthProvider: # later self.count = None try: - # we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree + # we will set this to True if we find out that discovering a node in the object takes more steps than the overall size of the RB tree # if this gets set to True, then we will merrily return None for # any child from that moment on self.garbage = False self.Mt = self.valobj.GetChildMemberWithName('_M_t') self.Mimpl = self.Mt.GetChildMemberWithName('_M_impl') self.Mheader = self.Mimpl.GetChildMemberWithName('_M_header') - - map_type = self.valobj.GetType() - if map_type.IsReferenceType(): - logger >> "Dereferencing type" - map_type = map_type.GetDereferencedType() - - # Get the type of std::pair. It is the first template - # argument type of the 4th template argument to std::map. - allocator_type = map_type.GetTemplateArgumentType(3) - self.data_type = allocator_type.GetTemplateArgumentType(0) - if not self.data_type: - # GCC does not emit DW_TAG_template_type_parameter for - # std::allocator<...>. For such a case, get the type of - # std::pair from a member of std::map. - rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType() - self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1) - - # from libstdc++ implementation of _M_root for rbtree - self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent') - self.data_size = self.data_type.GetByteSize() - self.skip_size = self.Mheader.GetType().GetByteSize() + if not self.Mheader.IsValid(): + self.count = 0 + else: + map_type = self.valobj.GetType() + if map_type.IsReferenceType(): + logger >> "Dereferencing type" + map_type = map_type.GetDereferencedType() + + # Get the type of std::pair. It is the first template + # argument type of the 4th template argument to std::map. + allocator_type = map_type.GetTemplateArgumentType(3) + self.data_type = allocator_type.GetTemplateArgumentType(0) + if not self.data_type: + # GCC does not emit DW_TAG_template_type_parameter for + # std::allocator<...>. For such a case, get the type of + # std::pair from a member of std::map. + rep_type = self.valobj.GetChildMemberWithName('_M_t').GetType() + self.data_type = rep_type.GetTypedefedType().GetTemplateArgumentType(1) + + # from libstdc++ implementation of _M_root for rbtree + self.Mroot = self.Mheader.GetChildMemberWithName('_M_parent') + self.data_size = self.data_type.GetByteSize() + self.skip_size = self.Mheader.GetType().GetByteSize() except: - pass + self.count = 0 return False def num_children(self): @@ -481,3 +683,135 @@ class StdMapSynthProvider: return True _list_uses_loop_detector = True + +class StdDequeSynthProvider: + def __init__(self, valobj, d): + self.valobj = valobj + self.pointer_size = self.valobj.GetProcess().GetAddressByteSize() + self.count = None + self.block_size = -1 + self.element_size = -1 + self.find_block_size() + + + def find_block_size(self): + # in order to use the deque we must have the block size, or else + # it's impossible to know what memory addresses are valid + self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) + if not self.element_type.IsValid(): + return + self.element_size = self.element_type.GetByteSize() + # The block size (i.e. number of elements per subarray) is defined in + # this piece of code, so we need to replicate it. + # + # #define _GLIBCXX_DEQUE_BUF_SIZE 512 + # + # return (__size < _GLIBCXX_DEQUE_BUF_SIZE + # ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); + if self.element_size < 512: + self.block_size = 512 // self.element_size + else: + self.block_size = 1 + + def num_children(self): + if self.count is None: + return 0 + return self.count + + def has_children(self): + return True + + def get_child_index(self, name): + try: + return int(name.lstrip('[').rstrip(']')) + except: + return -1 + + def get_child_at_index(self, index): + if index < 0 or self.count is None: + return None + if index >= self.num_children(): + return None + try: + name = '[' + str(index) + ']' + # We first look for the element in the first subarray, + # which might be incomplete. + if index < self.first_node_size: + # The following statement is valid because self.first_elem is the pointer + # to the first element + return self.first_elem.CreateChildAtOffset(name, index * self.element_size, self.element_type) + + # Now the rest of the subarrays except for maybe the last one + # are going to be complete, so the final expression is simpler + i, j = divmod(index - self.first_node_size, self.block_size) + + # We first move to the beginning of the node/subarray were our element is + node = self.start_node.CreateChildAtOffset( + '', + (1 + i) * self.valobj.GetProcess().GetAddressByteSize(), + self.element_type.GetPointerType()) + return node.CreateChildAtOffset(name, j * self.element_size, self.element_type) + + except: + return None + + def update(self): + logger = lldb.formatters.Logger.Logger() + self.count = 0 + try: + # A deque is effectively a two-dim array, with fixed width. + # However, only a subset of this memory contains valid data + # since a deque may have some slack at the front and back in + # order to have O(1) insertion at both ends. + # The rows in active use are delimited by '_M_start' and + # '_M_finish'. + # + # To find the elements that are actually constructed, the 'start' + # variable tells which element in this NxM array is the 0th + # one. + if self.block_size < 0 or self.element_size < 0: + return False + + count = 0 + + impl = self.valobj.GetChildMemberWithName('_M_impl') + + # we calculate the size of the first node (i.e. first internal array) + self.start = impl.GetChildMemberWithName('_M_start') + self.start_node = self.start.GetChildMemberWithName('_M_node') + first_node_address = self.start_node.GetValueAsUnsigned(0) + first_node_last_elem = self.start.GetChildMemberWithName('_M_last').GetValueAsUnsigned(0) + self.first_elem = self.start.GetChildMemberWithName('_M_cur') + first_node_first_elem = self.first_elem.GetValueAsUnsigned(0) + + + finish = impl.GetChildMemberWithName('_M_finish') + last_node_address = finish.GetChildMemberWithName('_M_node').GetValueAsUnsigned(0) + last_node_first_elem = finish.GetChildMemberWithName('_M_first').GetValueAsUnsigned(0) + last_node_last_elem = finish.GetChildMemberWithName('_M_cur').GetValueAsUnsigned(0) + + if first_node_first_elem == 0 or first_node_last_elem == 0 or first_node_first_elem > first_node_last_elem: + return False + if last_node_first_elem == 0 or last_node_last_elem == 0 or last_node_first_elem > last_node_last_elem: + return False + + + if last_node_address == first_node_address: + self.first_node_size = (last_node_last_elem - first_node_first_elem) // self.element_size + count += self.first_node_size + else: + self.first_node_size = (first_node_last_elem - first_node_first_elem) // self.element_size + count += self.first_node_size + + # we calculate the size of the last node + finish = impl.GetChildMemberWithName('_M_finish') + last_node_address = finish.GetChildMemberWithName('_M_node').GetValueAsUnsigned(0) + count += (last_node_last_elem - last_node_first_elem) // self.element_size + + # we calculate the size of the intermediate nodes + num_intermediate_nodes = (last_node_address - first_node_address - 1) // self.valobj.GetProcess().GetAddressByteSize() + count += self.block_size * num_intermediate_nodes + self.count = count + except: + pass + return False diff --git a/gnu/llvm/lldb/examples/synthetic/libcxx.py b/gnu/llvm/lldb/examples/synthetic/libcxx.py index 97593725a24..531d26784af 100644 --- a/gnu/llvm/lldb/examples/synthetic/libcxx.py +++ b/gnu/llvm/lldb/examples/synthetic/libcxx.py @@ -657,16 +657,15 @@ class stddeque_SynthProvider: # static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16; # } if self.element_size < 256: - self.block_size = 4096 / self.element_size + self.block_size = 4096 // self.element_size else: self.block_size = 16 def num_children(self): - global _deque_capping_size logger = lldb.formatters.Logger.Logger() if self.count is None: return 0 - return min(self.count, _deque_capping_size) + return self.count def has_children(self): return True @@ -687,9 +686,10 @@ class stddeque_SynthProvider: return None try: i, j = divmod(self.start + index, self.block_size) + return self.first.CreateValueFromExpression( '[' + str(index) + ']', '*(*(%s + %d) + %d)' % - (self.first.get_expr_path(), i, j)) + (self.map_begin.get_expr_path(), i, j)) except: return None @@ -727,12 +727,14 @@ class stddeque_SynthProvider: '__start_').GetValueAsUnsigned(0) first = map_.GetChildMemberWithName('__first_') map_first = first.GetValueAsUnsigned(0) - map_begin = map_.GetChildMemberWithName( - '__begin_').GetValueAsUnsigned(0) + self.map_begin = map_.GetChildMemberWithName( + '__begin_') + map_begin = self.map_begin.GetValueAsUnsigned(0) map_end = map_.GetChildMemberWithName( '__end_').GetValueAsUnsigned(0) map_endcap = self._get_value_of_compressed_pair( map_.GetChildMemberWithName( '__end_cap_')) + # check consistency if not map_first <= map_begin <= map_end <= map_endcap: logger.write("map pointers are not monotonic") @@ -750,18 +752,7 @@ class stddeque_SynthProvider: if junk: logger.write("begin-first doesnt align correctly") return - if not start_row * \ - self.block_size <= start < (start_row + 1) * self.block_size: - logger.write("0th element must be in the 'begin' row") - return - end_row = start_row + active_rows - if not count: - if active_rows: - logger.write("empty deque but begin!=end") - return - elif not (end_row - 1) * self.block_size <= start + count < end_row * self.block_size: - logger.write("nth element must be before the 'end' row") - return + logger.write( "update success: count=%r, start=%r, first=%r" % (count, start, first)) @@ -774,6 +765,7 @@ class stddeque_SynthProvider: self.start = None self.map_first = None self.map_begin = None + return False class stdsharedptr_SynthProvider: @@ -873,4 +865,3 @@ def __lldb_init_module(debugger, dict): _map_capping_size = 255 _list_capping_size = 255 _list_uses_loop_detector = True -_deque_capping_size = 255 diff --git a/gnu/llvm/lldb/examples/synthetic/recognizer_function/example.py b/gnu/llvm/lldb/examples/synthetic/recognizer_function/example.py new file mode 100644 index 00000000000..f2d4f75d50e --- /dev/null +++ b/gnu/llvm/lldb/examples/synthetic/recognizer_function/example.py @@ -0,0 +1,63 @@ +# Formatters for classes that derive from Message. +# +# Usage: +# command script import ./example.py +# type summary add --expand --recognizer-function --python-function example.message_summary example.is_message_type +# type synth add --recognizer-function --python-class example.MessageChildProvider example.is_message_type + +import sys + +def is_message_type(t, internal_dict): + for base in t.get_bases_array(): + if base.GetName() == "Message": + return True + return False + +def message_summary(value, internal_dict): + # Could have used a summary string as well. All the work is done by the child + # provider. + return "Message" + +class MessageChildProvider: + def __init__(self, value, internal_dict): + self.value = value + self.synthetic_children = self._analyze_children(value) + + def has_children(self): + return self.num_children() > 0 + + def num_children(self): + return len(self.synthetic_children) + + def get_child_index(self, name): + for index, child in enumerate(self.synthetic_children): + if child.GetName() == name: + return index + return None + + def get_child_at_index(self, index): + return self.synthetic_children[index] + + def _rename_sbvalue(self, value): + # We want to display the field with its original name without a trailing + # underscore. So we create a new SBValue with the same type and address but + # a different name. + name = value.GetName() + assert name.endswith("_") + new_name = name[:-1] + return value.CreateValueFromAddress(new_name, value.GetLoadAddress(), + value.GetType()) + + def _analyze_children(self, value): + result = [] + for i in range(value.GetNumChildren()): + child = value.GetChildAtIndex(i) + child_name = child.GetName() + if child_name.startswith("_"): + continue # Internal field, skip + # Normal field. Check presence bit. + presence_bit = value.GetChildMemberWithName("_has_" + child_name) + if presence_bit.GetValueAsUnsigned() != 0: + result.append(self._rename_sbvalue(child)) + return result + diff --git a/gnu/llvm/lldb/examples/synthetic/recognizer_function/lldb-commands b/gnu/llvm/lldb/examples/synthetic/recognizer_function/lldb-commands new file mode 100644 index 00000000000..d45d8be5f47 --- /dev/null +++ b/gnu/llvm/lldb/examples/synthetic/recognizer_function/lldb-commands @@ -0,0 +1,7 @@ +command script import ./example.py +type summary add --expand --recognizer-function --python-function example.message_summary example.is_message_type +type synth add --recognizer-function --python-class example.MessageChildProvider example.is_message_type +b program.cpp:112 +r +p customer +p order diff --git a/gnu/llvm/lldb/examples/synthetic/recognizer_function/program.cpp b/gnu/llvm/lldb/examples/synthetic/recognizer_function/program.cpp new file mode 100644 index 00000000000..82672557365 --- /dev/null +++ b/gnu/llvm/lldb/examples/synthetic/recognizer_function/program.cpp @@ -0,0 +1,114 @@ +// Example program for matching summary functions and synthetic child providers. +// +// The classes here simulate code generated by a serialization tool like, for +// example, protocol buffers. But the actual "generated" class layout is +// extremely naive to simplify the example. +// +// The idea is that we want to have generic formatters for a bunch of message +// classes, because they are all generated following common patterns, but the +// matching can't be based in the type name, because it can be anything. + +#include + +class Message { + // Dummy method definitions to illustrate a possible generic message API. + std::string serialize() { return "TODO"; } + Message* deserialize() { + return nullptr; // TODO. + } +}; + +// This class could have been generated from a description like this. Assume +// fields are always optional, for simplicity (e.g. we don't care during +// serialization if a Customer has a name or not, we're just moving data around +// and validation happens elsewhere). +// +// message Customer { +// string name; +// int age; +// string address; +// } +class Customer : public Message { + private: + int _internal_bookkeeping_bits_; + + // Presence bits. They are true if the field has been set. + bool _has_name_ = false; + bool _has_age_ = false; + bool _has_address_ = false; + + // Actual field data. + std::string name_; + int age_; + std::string address_; + + public: + // Getters and setters. + bool has_name() { return _has_name_; } + bool has_age() { return _has_age_; } + bool has_address() { return _has_address_; } + + std::string name() { return name_; } + int age() { return age_; } + std::string address() { return address_; } + + void set_name(std::string name) { + name_ = name; + _has_name_ = true; + } + void set_age(int age) { + age_ = age; + _has_age_ = true; + } + void set_address(std::string address) { + address_ = address; + _has_address_ = true; + } +}; + +// message ProductOrder { +// string product_name; +// int amount; +// } +class ProductOrder : public Message { + private: + int _internal_bookkeeping_bits_; + + // Presence bits. They are true if the field has been set. + bool _has_product_name_ = false; + bool _has_amount_ = false; + + // Actual field data. + std::string product_name_; + int amount_; + + public: + // Getters and setters. + bool has_product_name() { return _has_product_name_; } + bool has_amount() { return _has_amount_; } + + std::string get_product_name() { return product_name_; } + int get_amount() { return amount_; } + + void set_product_name(std::string product_name) { + product_name_ = product_name; + _has_product_name_ = true; + } + void set_amount(int amount) { + amount_ = amount; + _has_amount_ = true; + } +}; + +int main(int argc, char **argv) { + Customer customer; + customer.set_name("C. Ustomer"); + customer.set_address("123 Fake St."); + // no age, so we can check absent fields get omitted. + + ProductOrder order; + order.set_product_name("widget"); + order.set_amount(100); + return 0; // break here. +} + diff --git a/gnu/llvm/lldb/include/lldb/API/SBBreakpointLocation.h b/gnu/llvm/lldb/include/lldb/API/SBBreakpointLocation.h index a906727f938..ca29696065e 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBBreakpointLocation.h +++ b/gnu/llvm/lldb/include/lldb/API/SBBreakpointLocation.h @@ -48,11 +48,13 @@ public: void SetCondition(const char *condition); const char *GetCondition(); - + void SetAutoContinue(bool auto_continue); bool GetAutoContinue(); + void SetCallback(SBBreakpointHitCallback callback, void *baton); + void SetScriptCallbackFunction(const char *callback_function_name); SBError SetScriptCallbackFunction(const char *callback_function_name, diff --git a/gnu/llvm/lldb/include/lldb/API/SBCommandInterpreter.h b/gnu/llvm/lldb/include/lldb/API/SBCommandInterpreter.h index 2364a8dae88..0d344fc7fbc 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/gnu/llvm/lldb/include/lldb/API/SBCommandInterpreter.h @@ -59,6 +59,8 @@ public: bool HasAliasOptions(); + bool IsInteractive(); + lldb::SBProcess GetProcess(); lldb::SBDebugger GetDebugger(); @@ -145,6 +147,8 @@ public: const char *help, const char *syntax, const char *auto_repeat_command); + void SourceInitFileInGlobalDirectory(lldb::SBCommandReturnObject &result); + void SourceInitFileInHomeDirectory(lldb::SBCommandReturnObject &result); void SourceInitFileInHomeDirectory(lldb::SBCommandReturnObject &result, bool is_repl); diff --git a/gnu/llvm/lldb/include/lldb/API/SBCommunication.h b/gnu/llvm/lldb/include/lldb/API/SBCommunication.h index e407d859d88..fa8c88acd3f 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBCommunication.h +++ b/gnu/llvm/lldb/include/lldb/API/SBCommunication.h @@ -75,7 +75,7 @@ private: SBCommunication(const SBCommunication &) = delete; const SBCommunication &operator=(const SBCommunication &) = delete; - lldb_private::Communication *m_opaque = nullptr; + lldb_private::ThreadedCommunication *m_opaque = nullptr; bool m_opaque_owned = false; }; diff --git a/gnu/llvm/lldb/include/lldb/API/SBCompileUnit.h b/gnu/llvm/lldb/include/lldb/API/SBCompileUnit.h index d965b9d966b..36492d9398c 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBCompileUnit.h +++ b/gnu/llvm/lldb/include/lldb/API/SBCompileUnit.h @@ -34,6 +34,9 @@ public: lldb::SBLineEntry GetLineEntryAtIndex(uint32_t idx) const; + uint32_t FindLineEntryIndex(lldb::SBLineEntry &line_entry, + bool exact = false) const; + uint32_t FindLineEntryIndex(uint32_t start_idx, uint32_t line, lldb::SBFileSpec *inline_file_spec) const; diff --git a/gnu/llvm/lldb/include/lldb/API/SBData.h b/gnu/llvm/lldb/include/lldb/API/SBData.h index 85c8110e181..89a699f2f71 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBData.h +++ b/gnu/llvm/lldb/include/lldb/API/SBData.h @@ -83,6 +83,9 @@ public: void SetData(lldb::SBError &error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + void SetDataWithOwnership(lldb::SBError &error, const void *buf, size_t size, + lldb::ByteOrder endian, uint8_t addr_size); + // see SetData() for why we don't have Append(const void* buf, size_t size) bool Append(const SBData &rhs); diff --git a/gnu/llvm/lldb/include/lldb/API/SBDebugger.h b/gnu/llvm/lldb/include/lldb/API/SBDebugger.h index ef62141f579..950e8e29ef7 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBDebugger.h +++ b/gnu/llvm/lldb/include/lldb/API/SBDebugger.h @@ -33,7 +33,11 @@ public: class LLDB_API SBDebugger { public: - FLAGS_ANONYMOUS_ENUM(){eBroadcastBitProgress = (1 << 0)}; + FLAGS_ANONYMOUS_ENUM(){ + eBroadcastBitProgress = (1 << 0), + eBroadcastBitWarning = (1 << 1), + eBroadcastBitError = (1 << 2), + }; SBDebugger(); @@ -79,12 +83,19 @@ public: uint64_t &completed, uint64_t &total, bool &is_debugger_specific); + static lldb::SBStructuredData + GetDiagnosticFromEvent(const lldb::SBEvent &event); + lldb::SBDebugger &operator=(const lldb::SBDebugger &rhs); static void Initialize(); static lldb::SBError InitializeWithErrorHandling(); + static void PrintStackTraceOnError(); + + static void PrintDiagnosticsOnError(); + static void Terminate(); // Deprecated, use the one that takes a source_init_files bool. @@ -106,6 +117,21 @@ public: void Clear(); + /// Getting a specific setting value into SBStructuredData format. + /// Client can specify empty string or null to get all settings. + /// + /// Example usages: + /// lldb::SBStructuredData settings = debugger.GetSetting(); + /// lldb::SBStructuredData settings = debugger.GetSetting(nullptr); + /// lldb::SBStructuredData settings = debugger.GetSetting(""); + /// lldb::SBStructuredData settings = debugger.GetSetting("target.arg0"); + /// lldb::SBStructuredData settings = debugger.GetSetting("target"); + /// + /// \param[out] setting + /// Property setting path to retrieve values. e.g "target.source-map" + /// + lldb::SBStructuredData GetSetting(const char *setting = nullptr); + void SetAsync(bool b); bool GetAsync(); @@ -126,6 +152,8 @@ public: FILE *GetErrorFileHandle(); + SBError SetInputString(const char *data); + SBError SetInputFile(SBFile file); SBError SetOutputFile(SBFile file); @@ -247,6 +275,8 @@ public: lldb::ScriptLanguage GetScriptingLanguage(const char *script_language_name); + SBStructuredData GetScriptInterpreterInfo(ScriptLanguage); + static const char *GetVersionString(); static const char *StateAsCString(lldb::StateType state); @@ -302,6 +332,10 @@ public: void SetScriptLanguage(lldb::ScriptLanguage script_lang); + lldb::LanguageType GetREPLLanguage() const; + + void SetREPLLanguage(lldb::LanguageType repl_lang); + bool GetCloseInputOnEOF() const; void SetCloseInputOnEOF(bool b); @@ -374,6 +408,17 @@ public: SBError RunREPL(lldb::LanguageType language, const char *repl_options); + /// Load a trace from a trace description file and create Targets, + /// Processes and Threads based on the contents of such file. + /// + /// \param[out] error + /// An error if the trace could not be created. + /// + /// \param[in] trace_description_file + /// The file containing the necessary information to load the trace. + SBTrace LoadTraceFromFile(SBError &error, + const SBFileSpec &trace_description_file); + private: friend class SBCommandInterpreter; friend class SBInputReader; @@ -381,6 +426,7 @@ private: friend class SBProcess; friend class SBSourceManager; friend class SBTarget; + friend class SBTrace; lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP); diff --git a/gnu/llvm/lldb/include/lldb/API/SBDefines.h b/gnu/llvm/lldb/include/lldb/API/SBDefines.h index 3ab10ad8e06..6833c0542c1 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBDefines.h +++ b/gnu/llvm/lldb/include/lldb/API/SBDefines.h @@ -15,6 +15,18 @@ #include "lldb/lldb-types.h" #include "lldb/lldb-versioning.h" +#ifndef LLDB_API +#if defined(_WIN32) +#if defined(LLDB_IN_LIBLLDB) +#define LLDB_API __declspec(dllexport) +#else +#define LLDB_API __declspec(dllimport) +#endif +#else // defined (_WIN32) +#define LLDB_API +#endif +#endif + // Forward Declarations namespace lldb { @@ -76,6 +88,7 @@ class LLDB_API SBThread; class LLDB_API SBThreadCollection; class LLDB_API SBThreadPlan; class LLDB_API SBTrace; +class LLDB_API SBTraceCursor; class LLDB_API SBType; class LLDB_API SBTypeCategory; class LLDB_API SBTypeEnumMember; diff --git a/gnu/llvm/lldb/include/lldb/API/SBError.h b/gnu/llvm/lldb/include/lldb/API/SBError.h index f8289e2fcbb..e698ee9e933 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBError.h +++ b/gnu/llvm/lldb/include/lldb/API/SBError.h @@ -23,10 +23,16 @@ public: SBError(const lldb::SBError &rhs); + SBError(const lldb_private::Status &error); + ~SBError(); const SBError &operator=(const lldb::SBError &rhs); + /// Get the error string as a NULL terminated UTF8 c-string. + /// + /// This SBError object owns the returned string and this object must be kept + /// around long enough to use the returned string. const char *GetCString() const; void Clear(); @@ -64,6 +70,7 @@ protected: friend class SBCommunication; friend class SBData; friend class SBDebugger; + friend class SBFile; friend class SBHostOS; friend class SBPlatform; friend class SBProcess; @@ -73,8 +80,8 @@ protected: friend class SBThread; friend class SBTrace; friend class SBValue; + friend class SBValueList; friend class SBWatchpoint; - friend class SBFile; friend class lldb_private::ScriptInterpreter; diff --git a/gnu/llvm/lldb/include/lldb/API/SBExecutionContext.h b/gnu/llvm/lldb/include/lldb/API/SBExecutionContext.h index 06ece6fbc0f..70fc83e84e4 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBExecutionContext.h +++ b/gnu/llvm/lldb/include/lldb/API/SBExecutionContext.h @@ -50,8 +50,6 @@ public: SBFrame GetFrame() const; protected: - void reset(lldb::ExecutionContextRefSP &event_sp); - lldb_private::ExecutionContextRef *get() const; private: diff --git a/gnu/llvm/lldb/include/lldb/API/SBFileSpec.h b/gnu/llvm/lldb/include/lldb/API/SBFileSpec.h index a2f02ac7820..a286912f109 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBFileSpec.h +++ b/gnu/llvm/lldb/include/lldb/API/SBFileSpec.h @@ -74,6 +74,7 @@ private: friend class SBSourceManager; friend class SBTarget; friend class SBThread; + friend class SBTrace; SBFileSpec(const lldb_private::FileSpec &fspec); diff --git a/gnu/llvm/lldb/include/lldb/API/SBInstruction.h b/gnu/llvm/lldb/include/lldb/API/SBInstruction.h index b9d781550b5..def9482b02e 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBInstruction.h +++ b/gnu/llvm/lldb/include/lldb/API/SBInstruction.h @@ -43,6 +43,8 @@ public: const char *GetComment(lldb::SBTarget target); + lldb::InstructionControlFlowKind GetControlFlowKind(lldb::SBTarget target); + lldb::SBData GetData(lldb::SBTarget target); size_t GetByteSize(); diff --git a/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfo.h b/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfo.h index 122226b9a0c..be55de4ead1 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfo.h +++ b/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfo.h @@ -20,6 +20,10 @@ public: SBMemoryRegionInfo(const lldb::SBMemoryRegionInfo &rhs); + SBMemoryRegionInfo(const char *name, lldb::addr_t begin, lldb::addr_t end, + uint32_t permissions, bool mapped, + bool stack_memory = false); + ~SBMemoryRegionInfo(); const lldb::SBMemoryRegionInfo & @@ -117,6 +121,8 @@ private: friend class SBProcess; friend class SBMemoryRegionInfoList; + friend class lldb_private::ScriptInterpreter; + lldb_private::MemoryRegionInfo &ref(); const lldb_private::MemoryRegionInfo &ref() const; diff --git a/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfoList.h b/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfoList.h index a7122ee9108..1d939dff55f 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfoList.h +++ b/gnu/llvm/lldb/include/lldb/API/SBMemoryRegionInfoList.h @@ -27,6 +27,9 @@ public: uint32_t GetSize() const; + bool GetMemoryRegionContainingAddress(lldb::addr_t addr, + SBMemoryRegionInfo ®ion_info); + bool GetMemoryRegionAtIndex(uint32_t idx, SBMemoryRegionInfo ®ion_info); void Append(lldb::SBMemoryRegionInfo ®ion); diff --git a/gnu/llvm/lldb/include/lldb/API/SBModule.h b/gnu/llvm/lldb/include/lldb/API/SBModule.h index dd783fe4107..7200a1ef53f 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBModule.h +++ b/gnu/llvm/lldb/include/lldb/API/SBModule.h @@ -37,6 +37,8 @@ public: void Clear(); + bool IsFileBacked() const; + /// Get const accessor for the module file specification. /// /// This function returns the file for the module on the host system diff --git a/gnu/llvm/lldb/include/lldb/API/SBPlatform.h b/gnu/llvm/lldb/include/lldb/API/SBPlatform.h index 98291f18247..dcc8a14ff0c 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBPlatform.h +++ b/gnu/llvm/lldb/include/lldb/API/SBPlatform.h @@ -137,6 +137,8 @@ public: uint32_t GetOSUpdateVersion(); + void SetSDKRoot(const char *sysroot); + SBError Put(SBFileSpec &src, SBFileSpec &dst); SBError Get(SBFileSpec &src, SBFileSpec &dst); diff --git a/gnu/llvm/lldb/include/lldb/API/SBProcess.h b/gnu/llvm/lldb/include/lldb/API/SBProcess.h index 73a8d918f4d..49b3256869e 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBProcess.h +++ b/gnu/llvm/lldb/include/lldb/API/SBProcess.h @@ -337,7 +337,21 @@ public: bool IsInstrumentationRuntimePresent(InstrumentationRuntimeType type); - /// Save the state of the process in a core file (or mini dump on Windows). + /// Save the state of the process in a core file. + /// + /// \param[in] file_name - The name of the file to save the core file to. + /// + /// \param[in] flavor - Specify the flavor of a core file plug-in to save. + /// Currently supported flavors include "mach-o" and "minidump" + /// + /// \param[in] core_style - Specify the style of a core file to save. + lldb::SBError SaveCore(const char *file_name, const char *flavor, + SaveCoreStyle core_style); + + /// Save the state of the process with the a flavor that matches the + /// current process' main executable (if supported). + /// + /// \param[in] file_name - The name of the file to save the core file to. lldb::SBError SaveCore(const char *file_name); /// Query the address load_addr and store the details of the memory diff --git a/gnu/llvm/lldb/include/lldb/API/SBReproducer.h b/gnu/llvm/lldb/include/lldb/API/SBReproducer.h index ecf28d6f0e1..f84645eff01 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBReproducer.h +++ b/gnu/llvm/lldb/include/lldb/API/SBReproducer.h @@ -32,9 +32,6 @@ public: void SetCheckVersion(bool check); bool GetCheckVersion() const; - -private: - std::unique_ptr m_opaque_up; }; /// The SBReproducer class is special because it bootstraps the capture and diff --git a/gnu/llvm/lldb/include/lldb/API/SBSection.h b/gnu/llvm/lldb/include/lldb/API/SBSection.h index d722dbe4ff1..94c6614ecfa 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBSection.h +++ b/gnu/llvm/lldb/include/lldb/API/SBSection.h @@ -76,6 +76,12 @@ public: /// The number of host (8-bit) bytes needed to hold a target byte uint32_t GetTargetByteSize(); + /// Return the alignment of the section in bytes + /// + /// \return + /// The alignment of the section in bytes + uint32_t GetAlignment(); + bool operator==(const lldb::SBSection &rhs); bool operator!=(const lldb::SBSection &rhs); diff --git a/gnu/llvm/lldb/include/lldb/API/SBStructuredData.h b/gnu/llvm/lldb/include/lldb/API/SBStructuredData.h index 07075abbf1d..533dcc8fc07 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBStructuredData.h +++ b/gnu/llvm/lldb/include/lldb/API/SBStructuredData.h @@ -22,7 +22,7 @@ public: SBStructuredData(const lldb::EventSP &event_sp); - SBStructuredData(lldb_private::StructuredDataImpl *impl); + SBStructuredData(const lldb_private::StructuredDataImpl &impl); ~SBStructuredData(); diff --git a/gnu/llvm/lldb/include/lldb/API/SBSymbol.h b/gnu/llvm/lldb/include/lldb/API/SBSymbol.h index 5935ccfed02..94521881f82 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBSymbol.h +++ b/gnu/llvm/lldb/include/lldb/API/SBSymbol.h @@ -41,10 +41,46 @@ public: lldb::SBInstructionList GetInstructions(lldb::SBTarget target, const char *flavor_string); + /// Get the start address of this symbol + /// + /// \returns + /// If the symbol's value is not an address, an invalid SBAddress object + /// will be returned. If the symbol's value is an address, a valid SBAddress + /// object will be returned. SBAddress GetStartAddress(); + /// Get the end address of this symbol + /// + /// \returns + /// If the symbol's value is not an address, an invalid SBAddress object + /// will be returned. If the symbol's value is an address, a valid SBAddress + /// object will be returned. SBAddress GetEndAddress(); + /// Get the raw value of a symbol. + /// + /// This accessor allows direct access to the symbol's value from the symbol + /// table regardless of what the value is. The value can be a file address or + /// it can be an integer value that depends on what the symbol's type is. Some + /// symbol values are not addresses, but absolute values or integer values + /// that can be mean different things. The GetStartAddress() accessor will + /// only return a valid SBAddress if the symbol's value is an address, so this + /// accessor provides a way to access the symbol's value when the value is + /// not an address. + /// + /// \returns + /// Returns the raw integer value of a symbol from the symbol table. + uint64_t GetValue(); + + /// Get the size of the symbol. + /// + /// This accessor allows direct access to the symbol's size from the symbol + /// table regardless of what the value is (address or integer value). + /// + /// \returns + /// Returns the size of a symbol from the symbol table. + uint64_t GetSize(); + uint32_t GetPrologueByteSize(); SymbolType GetType(); diff --git a/gnu/llvm/lldb/include/lldb/API/SBSymbolContext.h b/gnu/llvm/lldb/include/lldb/API/SBSymbolContext.h index 16ad29ea873..b4c5921d81a 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBSymbolContext.h +++ b/gnu/llvm/lldb/include/lldb/API/SBSymbolContext.h @@ -25,7 +25,7 @@ public: SBSymbolContext(const lldb::SBSymbolContext &rhs); - SBSymbolContext(const lldb_private::SymbolContext *sc_ptr); + SBSymbolContext(const lldb_private::SymbolContext &sc_ptr); ~SBSymbolContext(); @@ -72,8 +72,6 @@ protected: lldb_private::SymbolContext *get() const; - void SetSymbolContext(const lldb_private::SymbolContext *sc_ptr); - private: std::unique_ptr m_opaque_up; }; diff --git a/gnu/llvm/lldb/include/lldb/API/SBTarget.h b/gnu/llvm/lldb/include/lldb/API/SBTarget.h index 5a6908f040b..018acfd595a 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBTarget.h +++ b/gnu/llvm/lldb/include/lldb/API/SBTarget.h @@ -321,6 +321,8 @@ public: uint32_t GetAddressByteSize(); const char *GetTriple(); + + const char *GetABIName(); /// Architecture data byte width accessor /// @@ -336,6 +338,11 @@ public: /// unit from the Architecture's code bus uint32_t GetCodeByteSize(); + /// Gets the target.max-children-count value + /// It should be used to limit the number of + /// children of large data structures to be displayed. + uint32_t GetMaximumNumberOfChildrenToDisplay() const; + /// Set the base load address for a module section. /// /// \param[in] section diff --git a/gnu/llvm/lldb/include/lldb/API/SBThread.h b/gnu/llvm/lldb/include/lldb/API/SBThread.h index ac1b8407a22..924aae2f109 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBThread.h +++ b/gnu/llvm/lldb/include/lldb/API/SBThread.h @@ -208,6 +208,8 @@ public: bool SafeToCallFunctions(); + SBValue GetSiginfo(); + private: friend class SBBreakpoint; friend class SBBreakpointLocation; diff --git a/gnu/llvm/lldb/include/lldb/API/SBTrace.h b/gnu/llvm/lldb/include/lldb/API/SBTrace.h index 1685caaf4ef..7929d217ef2 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBTrace.h +++ b/gnu/llvm/lldb/include/lldb/API/SBTrace.h @@ -11,8 +11,7 @@ #include "lldb/API/SBDefines.h" #include "lldb/API/SBError.h" - -class TraceImpl; +#include "lldb/API/SBTraceCursor.h" namespace lldb { @@ -23,6 +22,46 @@ public: SBTrace(const lldb::TraceSP &trace_sp); + /// See SBDebugger::LoadTraceFromFile. + static SBTrace LoadTraceFromFile(SBError &error, SBDebugger &debugger, + const SBFileSpec &trace_description_file); + + /// Get a \a TraceCursor for the given thread's trace. + /// + /// \param[out] error + /// This will be set with an error in case of failures. + // + /// \param[in] thread + /// The thread to get a \a TraceCursor for. + // + /// \return + /// A \a SBTraceCursor. If the thread is not traced or its trace + /// information failed to load, an invalid \a SBTraceCursor is returned + /// and the \p error parameter is set. + SBTraceCursor CreateNewCursor(SBError &error, SBThread &thread); + + /// Save the trace to the specified directory, which will be created if + /// needed. This will also create a a file \a /trace.json with the + /// main properties of the trace session, along with others files which + /// contain the actual trace data. The trace.json file can be used later as + /// input for the "trace load" command to load the trace in LLDB, or for the + /// method \a SBDebugger.LoadTraceFromFile(). + /// + /// \param[out] error + /// This will be set with an error in case of failures. + /// + /// \param[in] directory + /// The directory where the trace files will be saved. + /// + /// \param[in] compact + /// Try not to save to disk information irrelevant to the traced processes. + /// Each trace plug-in implements this in a different fashion. + /// + /// \return + /// A \a SBFileSpec pointing to the bundle description file. + SBFileSpec SaveToDisk(SBError &error, const SBFileSpec &bundle_dir, + bool compact = false); + /// \return /// A description of the parameters to use for the \a SBTrace::Start /// method, or \b null if the object is invalid. diff --git a/gnu/llvm/lldb/include/lldb/API/SBTraceCursor.h b/gnu/llvm/lldb/include/lldb/API/SBTraceCursor.h new file mode 100644 index 00000000000..c2f38b6b486 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/API/SBTraceCursor.h @@ -0,0 +1,181 @@ +//===-- SBTraceCursor.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_API_SBTRACECURSOR_H +#define LLDB_API_SBTRACECURSOR_H + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBExecutionContext.h" + +namespace lldb { + +class LLDB_API SBTraceCursor { +public: + /// Default constructor for an invalid \a SBTraceCursor object. + SBTraceCursor(); + + /// Create a cursor that initially points to the end of the trace, i.e. the + /// most recent item. + SBTraceCursor(lldb::TraceCursorSP trace_cursor_sp); + + /// Set the direction to use in the \a SBTraceCursor::Next() method. + /// + /// \param[in] forwards + /// If \b true, then the traversal will be forwards, otherwise backwards. + void SetForwards(bool forwards); + + /// Check if the direction to use in the \a SBTraceCursor::Next() method is + /// forwards. + /// + /// \return + /// \b true if the current direction is forwards, \b false if backwards. + bool IsForwards() const; + + /// Move the cursor to the next item (instruction or error). + /// + /// Direction: + /// The traversal is done following the current direction of the trace. If + /// it is forwards, the instructions are visited forwards + /// chronologically. Otherwise, the traversal is done in + /// the opposite direction. By default, a cursor moves backwards unless + /// changed with \a SBTraceCursor::SetForwards(). + void Next(); + + /// \return + /// \b true if the cursor is pointing to a valid item. \b false if the + /// cursor has reached the end of the trace. + bool HasValue() const; + + /// Instruction identifiers: + /// + /// When building complex higher level tools, fast random accesses in the + /// trace might be needed, for which each instruction requires a unique + /// identifier within its thread trace. For example, a tool might want to + /// repeatedly inspect random consecutive portions of a trace. This means that + /// it will need to first move quickly to the beginning of each section and + /// then start its iteration. Given that the number of instructions can be in + /// the order of hundreds of millions, fast random access is necessary. + /// + /// An example of such a tool could be an inspector of the call graph of a + /// trace, where each call is represented with its start and end instructions. + /// Inspecting all the instructions of a call requires moving to its first + /// instruction and then iterating until the last instruction, which following + /// the pattern explained above. + /// + /// Instead of using 0-based indices as identifiers, each Trace plug-in can + /// decide the nature of these identifiers and thus no assumptions can be made + /// regarding their ordering and sequentiality. The reason is that an + /// instruction might be encoded by the plug-in in a way that hides its actual + /// 0-based index in the trace, but it's still possible to efficiently find + /// it. + /// + /// Requirements: + /// - For a given thread, no two instructions have the same id. + /// - In terms of efficiency, moving the cursor to a given id should be as + /// fast as possible, but not necessarily O(1). That's why the recommended + /// way to traverse sequential instructions is to use the \a + /// SBTraceCursor::Next() method and only use \a SBTraceCursor::GoToId(id) + /// sparingly. + + /// Make the cursor point to the item whose identifier is \p id. + /// + /// \return + /// \b true if the given identifier exists and the cursor effectively + /// moved to it. Otherwise, \b false is returned and the cursor now points + /// to an invalid item, i.e. calling \a HasValue() will return \b false. + bool GoToId(lldb::user_id_t id); + + /// \return + /// \b true if and only if there's an instruction item with the given \p + /// id. + bool HasId(lldb::user_id_t id) const; + + /// \return + /// A unique identifier for the instruction or error this cursor is + /// pointing to. + lldb::user_id_t GetId() const; + /// \} + + /// Make the cursor point to an item in the trace based on an origin point and + /// an offset. + /// + /// The resulting position of the trace is + /// origin + offset + /// + /// If this resulting position would be out of bounds, the trace then points + /// to an invalid item, i.e. calling \a HasValue() returns \b false. + /// + /// \param[in] offset + /// How many items to move forwards (if positive) or backwards (if + /// negative) from the given origin point. For example, if origin is \b + /// End, then a negative offset would move backward in the trace, but a + /// positive offset would move past the trace to an invalid item. + /// + /// \param[in] origin + /// The reference point to use when moving the cursor. + /// + /// \return + /// \b true if and only if the cursor ends up pointing to a valid item. + bool Seek(int64_t offset, lldb::TraceCursorSeekType origin); + + /// \return + /// The \a ExecutionContextRef of the backing thread from the creation time + /// of this cursor. + SBExecutionContext &GetExecutionContextRef(); + + /// Trace item information (instructions, errors and events) + /// \{ + + /// \return + /// The kind of item the cursor is pointing at. + lldb::TraceItemKind GetItemKind() const; + + /// \return + /// Whether the cursor points to an error or not. + bool IsError() const; + + /// \return + /// The error message the cursor is pointing at. + const char *GetError() const; + + /// \return + /// Whether the cursor points to an event or not. + bool IsEvent() const; + + /// \return + /// The specific kind of event the cursor is pointing at. + lldb::TraceEvent GetEventType() const; + + /// \return + /// A human-readable description of the event this cursor is pointing at. + const char *GetEventTypeAsString() const; + + /// \return + /// Whether the cursor points to an instruction. + bool IsInstruction() const; + + /// \return + /// The load address of the instruction the cursor is pointing at. + lldb::addr_t GetLoadAddress() const; + + /// \return + /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is + /// not available for the current item. + lldb::cpu_id_t GetCPU() const; + + bool IsValid() const; + + explicit operator bool() const; + +protected: + lldb::TraceCursorSP m_opaque_sp; +}; +} // namespace lldb + +#endif // LLDB_API_SBTRACECURSOR_H diff --git a/gnu/llvm/lldb/include/lldb/API/SBType.h b/gnu/llvm/lldb/include/lldb/API/SBType.h index 529b4d0eeff..215e03fad99 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBType.h +++ b/gnu/llvm/lldb/include/lldb/API/SBType.h @@ -106,6 +106,7 @@ public: SBType(); SBType(const lldb::SBType &rhs); + SBType(const lldb::TypeImplSP &); ~SBType(); @@ -133,6 +134,8 @@ public: bool IsScopedEnumerationType(); + bool IsAggregateType(); + lldb::SBType GetPointerType(); lldb::SBType GetPointeeType(); @@ -180,6 +183,8 @@ public: lldb::SBType GetTemplateArgumentType(uint32_t idx); + /// Return the TemplateArgumentKind of the template argument at index idx. + /// Variadic argument packs are automatically expanded. lldb::TemplateArgumentKind GetTemplateArgumentKind(uint32_t idx); lldb::SBType GetFunctionReturnType(); @@ -235,7 +240,6 @@ protected: SBType(const lldb_private::CompilerType &); SBType(const lldb::TypeSP &); - SBType(const lldb::TypeImplSP &); }; class SBTypeList { diff --git a/gnu/llvm/lldb/include/lldb/API/SBTypeNameSpecifier.h b/gnu/llvm/lldb/include/lldb/API/SBTypeNameSpecifier.h index eee424c1710..56a85d72c72 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBTypeNameSpecifier.h +++ b/gnu/llvm/lldb/include/lldb/API/SBTypeNameSpecifier.h @@ -20,6 +20,9 @@ public: SBTypeNameSpecifier(const char *name, bool is_regex = false); + SBTypeNameSpecifier(const char *name, + lldb::FormatterMatchType match_type); + SBTypeNameSpecifier(SBType type); SBTypeNameSpecifier(const lldb::SBTypeNameSpecifier &rhs); @@ -34,6 +37,8 @@ public: SBType GetType(); + lldb::FormatterMatchType GetMatchType(); + bool IsRegex(); bool GetDescription(lldb::SBStream &description, diff --git a/gnu/llvm/lldb/include/lldb/API/SBTypeSummary.h b/gnu/llvm/lldb/include/lldb/API/SBTypeSummary.h index 929bfb6124b..e9963682f7a 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBTypeSummary.h +++ b/gnu/llvm/lldb/include/lldb/API/SBTypeSummary.h @@ -19,7 +19,7 @@ public: SBTypeSummaryOptions(const lldb::SBTypeSummaryOptions &rhs); - SBTypeSummaryOptions(const lldb_private::TypeSummaryOptions *lldb_object_ptr); + SBTypeSummaryOptions(const lldb_private::TypeSummaryOptions &lldb_object); ~SBTypeSummaryOptions(); @@ -48,8 +48,6 @@ protected: const lldb_private::TypeSummaryOptions &ref() const; - void SetOptions(const lldb_private::TypeSummaryOptions *lldb_object_ptr); - private: std::unique_ptr m_opaque_up; }; diff --git a/gnu/llvm/lldb/include/lldb/API/SBValue.h b/gnu/llvm/lldb/include/lldb/API/SBValue.h index 69be02545b3..a8578abec6b 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBValue.h +++ b/gnu/llvm/lldb/include/lldb/API/SBValue.h @@ -246,6 +246,12 @@ public: bool SetData(lldb::SBData &data, lldb::SBError &error); + /// Creates a copy of the SBValue with a new name and setting the current + /// SBValue as its parent. It should be used when we want to change the + /// name of a SBValue without modifying the actual SBValue itself + /// (e.g. sythetic child provider). + lldb::SBValue Clone(const char *new_name); + lldb::SBDeclaration GetDeclaration(); /// Find out if a SBValue might have children. diff --git a/gnu/llvm/lldb/include/lldb/API/SBValueList.h b/gnu/llvm/lldb/include/lldb/API/SBValueList.h index dc8389b7529..a5017bccc50 100644 --- a/gnu/llvm/lldb/include/lldb/API/SBValueList.h +++ b/gnu/llvm/lldb/include/lldb/API/SBValueList.h @@ -43,6 +43,33 @@ public: const lldb::SBValueList &operator=(const lldb::SBValueList &rhs); + // Get an error for why this list is empty. + // + // If this list is empty, check for an underlying error in the debug + // information that prevented this list from being populated. This is not + // meant to return an error if there is no debug information as it is ok for a + // value list to be empty and no error should be returned in that case. If the + // debug info is for an assembly file or language that doesn't have any + // variables, no error should be returned. + // + // This is designed as a way to let users know when they enable certain + // compiler options that enable debug information but provide a degraded + // debug information content, like -gline-tables-only, which is a compiler + // option that allows users to set file and line breakpoints, but users get + // confused when no variables show up during debugging. + // + // It is also designed to inform a user that debug information might be + // available if an external file, like a .dwo file, but that file doesn't + // exist or wasn't able to be loaded due to a mismatched ID. When debugging + // with fission enabled, the line tables are linked into the main executable, + // but if the .dwo or .dwp files are not available or have been modified, + // users can get confused if they can stop at a file and line breakpoint but + // can't see variables in this case. + // + // This error can give vital clues to the user about the cause is and allow + // the user to fix the issue. + lldb::SBError GetError(); + protected: // only useful for visualizing the pointer or comparing two SBValueLists to // see if they are backed by the same underlying Impl. @@ -68,6 +95,8 @@ private: ValueListImpl &ref(); std::unique_ptr m_opaque_up; + + void SetError(const lldb_private::Status &status); }; } // namespace lldb diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/Breakpoint.h b/gnu/llvm/lldb/include/lldb/Breakpoint/Breakpoint.h index f2e2a0d2278..7490982cb05 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -22,6 +22,7 @@ #include "lldb/Breakpoint/Stoppoint.h" #include "lldb/Breakpoint/StoppointHitCounter.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Target/Statistics.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/StringList.h" #include "lldb/Utility/StructuredData.h" @@ -80,6 +81,8 @@ class Breakpoint : public std::enable_shared_from_this, public Stoppoint { public: static ConstString GetEventIdentifier(); + static const char * + BreakpointEventTypeAsCString(lldb::BreakpointEventType type); /// An enum specifying the match style for breakpoint settings. At present /// only used for function name style breakpoints. @@ -104,12 +107,14 @@ public: ~BreakpointEventData() override; static ConstString GetFlavorString(); + + Log *GetLogChannel() override; ConstString GetFlavor() const override; lldb::BreakpointEventType GetBreakpointEventType() const; - lldb::BreakpointSP &GetBreakpoint(); + lldb::BreakpointSP GetBreakpoint() const; BreakpointLocationCollection &GetBreakpointLocationCollection() { return m_locations; @@ -325,6 +330,9 @@ public: /// The current hit count for all locations. uint32_t GetHitCount() const; + /// Resets the current hit count for all locations. + void ResetHitCount(); + /// If \a one_shot is \b true, breakpoint will be deleted on first hit. void SetOneShot(bool one_shot); @@ -374,7 +382,10 @@ public: /// \param[in] is_synchronous /// If \b true the callback will be run on the private event thread /// before the stop event gets reported. If false, the callback will get - /// handled on the public event thread after the stop has been posted. + /// handled on the public event thread while the stop event is being + /// pulled off the event queue. + /// Note: synchronous callbacks cannot cause the target to run, in + /// particular, they should not try to run the expression evaluator. void SetCallback(BreakpointHitCallback callback, void *baton, bool is_synchronous = false); @@ -576,6 +587,12 @@ public: static lldb::BreakpointSP CopyFromBreakpoint(lldb::TargetSP new_target, const Breakpoint &bp_to_copy_from); + /// Get statistics associated with this breakpoint in JSON format. + llvm::json::Value GetStatistics(); + + /// Get the time it took to resolve all locations in this breakpoint. + StatsDuration::Duration GetResolveTime() const { return m_resolve_time; } + protected: friend class Target; // Protected Methods @@ -653,6 +670,8 @@ private: BreakpointName::Permissions m_permissions; + StatsDuration m_resolve_time; + void SendBreakpointChangedEvent(lldb::BreakpointEventType eventKind); void SendBreakpointChangedEvent(BreakpointEventData *data); diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointID.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointID.h index 64432f2d3cd..a62323061b7 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointID.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointID.h @@ -12,8 +12,8 @@ #include "lldb/lldb-private.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include namespace lldb_private { @@ -55,9 +55,9 @@ public: /// A string containing JUST the breakpoint description. /// \return /// If \p input was not a valid breakpoint ID string, returns - /// \b llvm::None. Otherwise returns a BreakpointID with members filled + /// \b std::nullopt. Otherwise returns a BreakpointID with members filled /// out accordingly. - static llvm::Optional + static std::optional ParseCanonicalReference(llvm::StringRef input); /// Takes an input string and checks to see whether it is a breakpoint name. diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointList.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointList.h index 346972ec3a1..a7399d385f6 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -138,6 +138,9 @@ public: void ClearAllBreakpointSites(); + /// Resets the hit count of all breakpoints. + void ResetHitCounts(); + /// Sets the passed in Locker to hold the Breakpoint List mutex. /// /// \param[in] lock diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocation.h index a6d1232162f..2a4f9fc01bf 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocation.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocation.h @@ -87,6 +87,9 @@ public: /// Return the current Hit Count. uint32_t GetHitCount() const { return m_hit_counter.GetValue(); } + /// Resets the current Hit Count. + void ResetHitCount() { m_hit_counter.Reset(); } + /// Return the current Ignore Count. /// /// \return diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocationList.h index 4b36c919ee3..f76a8fcfdd7 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointLocationList.h @@ -126,6 +126,9 @@ public: /// Hit count of all locations in this list. uint32_t GetHitCount() const; + /// Resets the hit count of all locations in this list. + void ResetHitCount(); + /// Enquires of the breakpoint location in this list with ID \a breakID /// whether we should stop. /// diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointOptions.h index 7b78265920a..7bf54571742 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointOptions.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointOptions.h @@ -43,11 +43,10 @@ public: | eCondition | eAutoContinue) }; struct CommandData { - CommandData() : user_source(), script_source() {} + CommandData() = default; CommandData(const StringList &user_source, lldb::ScriptLanguage interp) - : user_source(user_source), script_source(), interpreter(interp), - stop_on_error(true) {} + : user_source(user_source), interpreter(interp), stop_on_error(true) {} virtual ~CommandData() = default; @@ -195,8 +194,8 @@ public: /// The commands will be appended to this list. /// /// \return - /// \btrue if the command callback is a command-line callback, - /// \bfalse otherwise. + /// \b true if the command callback is a command-line callback, + /// \b false otherwise. bool GetCommandLineCallbacks(StringList &command_list); /// Remove the callback from this option set. diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolver.h index 7aa43b9f45d..a0b37c94ac2 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolver.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolver.h @@ -16,6 +16,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/lldb-private.h" +#include namespace lldb_private { @@ -205,7 +206,7 @@ protected: void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, llvm::StringRef log_ident, uint32_t line = 0, - llvm::Optional column = llvm::None); + std::optional column = std::nullopt); void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool, const char *) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h index bd8d0394d4d..5864a284d6f 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -11,6 +11,7 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Core/SourceLocationSpec.h" +#include namespace lldb_private { @@ -21,9 +22,10 @@ namespace lldb_private { class BreakpointResolverFileLine : public BreakpointResolver { public: - BreakpointResolverFileLine(const lldb::BreakpointSP &bkpt, - lldb::addr_t offset, bool skip_prologue, - const SourceLocationSpec &location_spec); + BreakpointResolverFileLine( + const lldb::BreakpointSP &bkpt, lldb::addr_t offset, bool skip_prologue, + const SourceLocationSpec &location_spec, + std::optional removed_prefix_opt = std::nullopt); static BreakpointResolver * CreateFromStructuredData(const lldb::BreakpointSP &bkpt, @@ -56,11 +58,15 @@ public: CopyForBreakpoint(lldb::BreakpointSP &breakpoint) override; protected: - void FilterContexts(SymbolContextList &sc_list, bool is_relative); + void FilterContexts(SymbolContextList &sc_list); + void DeduceSourceMapping(SymbolContextList &sc_list); friend class Breakpoint; SourceLocationSpec m_location_spec; bool m_skip_prologue; + // Any previously removed file path prefix by reverse source mapping. + // This is used to auto deduce source map if needed. + std::optional m_removed_prefix_opt; private: BreakpointResolverFileLine(const BreakpointResolverFileLine &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h index 26fd6f2f04d..cecd0f92a21 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h @@ -9,10 +9,10 @@ #ifndef LLDB_BREAKPOINT_BREAKPOINTRESOLVERSCRIPTED_H #define LLDB_BREAKPOINT_BREAKPOINTRESOLVERSCRIPTED_H -#include "lldb/lldb-forward.h" #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Core/ModuleSpec.h" - +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/lldb-forward.h" namespace lldb_private { @@ -26,7 +26,7 @@ public: BreakpointResolverScripted(const lldb::BreakpointSP &bkpt, const llvm::StringRef class_name, lldb::SearchDepth depth, - StructuredDataImpl *args_data); + const StructuredDataImpl &args_data); ~BreakpointResolverScripted() override = default; @@ -64,10 +64,7 @@ private: std::string m_class_name; lldb::SearchDepth m_depth; - StructuredDataImpl *m_args_ptr; // We own this, but the implementation - // has to manage the UP (since that is - // how it gets stored in the - // SBStructuredData). + StructuredDataImpl m_args; StructuredData::GenericSP m_implementation_sp; BreakpointResolverScripted(const BreakpointResolverScripted &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/Watchpoint.h b/gnu/llvm/lldb/include/lldb/Breakpoint/Watchpoint.h index 41b723a66b6..a5a72e3ad5a 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/Watchpoint.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/Watchpoint.h @@ -75,7 +75,7 @@ public: bool IsHardware() const override; bool ShouldStop(StoppointCallbackContext *context) override; - + bool WatchpointRead() const; bool WatchpointWrite() const; uint32_t GetIgnoreCount() const; @@ -157,12 +157,15 @@ public: private: friend class Target; friend class WatchpointList; + friend class StopInfoWatchpoint; // This needs to call UndoHitCount() void ResetHistoricValues() { m_old_value_sp.reset(); m_new_value_sp.reset(); } + void UndoHitCount() { m_hit_counter.Decrement(); } + Target &m_target; bool m_enabled; // Is this watchpoint enabled bool m_is_hardware; // Is this a hardware watchpoint diff --git a/gnu/llvm/lldb/include/lldb/Breakpoint/WatchpointOptions.h b/gnu/llvm/lldb/include/lldb/Breakpoint/WatchpointOptions.h index fbfcb91c424..369120e9853 100644 --- a/gnu/llvm/lldb/include/lldb/Breakpoint/WatchpointOptions.h +++ b/gnu/llvm/lldb/include/lldb/Breakpoint/WatchpointOptions.h @@ -166,7 +166,7 @@ public: lldb::user_id_t watch_id); struct CommandData { - CommandData() : user_source(), script_source() {} + CommandData() = default; ~CommandData() = default; diff --git a/gnu/llvm/lldb/include/lldb/Core/Address.h b/gnu/llvm/lldb/include/lldb/Core/Address.h index ec393a1871e..b19e6944275 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Address.h +++ b/gnu/llvm/lldb/include/lldb/Core/Address.h @@ -116,7 +116,7 @@ public: /// /// Initialize with a invalid section (NULL) and an invalid offset /// (LLDB_INVALID_ADDRESS). - Address() : m_section_wp() {} + Address() = default; /// Copy constructor /// @@ -210,6 +210,10 @@ public: } }; + /// Write a description of this object to a Stream. + bool GetDescription(Stream &s, Target &target, + lldb::DescriptionLevel level) const; + /// Dump a description of this object to a Stream. /// /// Dump a description of the contents of this object to the supplied stream @@ -225,6 +229,14 @@ public: /// \param[in] fallback_style /// The display style for the address. /// + /// \param[in] addr_byte_size + /// The address byte size for the address. + /// + /// \param[in] all_ranges + /// If true, dump all valid ranges and value ranges for the variable that + /// contains the address, otherwise dumping the range that contains the + /// address. + /// /// \return /// Returns \b true if the address was able to be displayed. /// File and load addresses may be unresolved and it may not be @@ -234,7 +246,8 @@ public: /// \see Address::DumpStyle bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style = DumpStyleInvalid, - uint32_t addr_byte_size = UINT32_MAX) const; + uint32_t addr_byte_size = UINT32_MAX, + bool all_ranges = false) const; AddressClass GetAddressClass() const; diff --git a/gnu/llvm/lldb/include/lldb/Core/AddressRange.h b/gnu/llvm/lldb/include/lldb/Core/AddressRange.h index 6fbdc35c916..4a33c2d7958 100644 --- a/gnu/llvm/lldb/include/lldb/Core/AddressRange.h +++ b/gnu/llvm/lldb/include/lldb/Core/AddressRange.h @@ -242,8 +242,6 @@ protected: lldb::addr_t m_byte_size = 0; ///< The size in bytes of this address range. }; -// bool operator== (const AddressRange& lhs, const AddressRange& rhs); - } // namespace lldb_private #endif // LLDB_CORE_ADDRESSRANGE_H diff --git a/gnu/llvm/lldb/include/lldb/Core/Communication.h b/gnu/llvm/lldb/include/lldb/Core/Communication.h index 930e927f678..f5f636816cb 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Communication.h +++ b/gnu/llvm/lldb/include/lldb/Core/Communication.h @@ -9,22 +9,15 @@ #ifndef LLDB_CORE_COMMUNICATION_H #define LLDB_CORE_COMMUNICATION_H -#include "lldb/Host/HostThread.h" -#include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" -#include #include -#include #include -#include -#include - namespace lldb_private { class Connection; class ConstString; @@ -38,90 +31,22 @@ class Status; /// approach has a couple of advantages: it allows a single instance of this /// class to be used even though its connection can change. Connections could /// negotiate for different connections based on abilities like starting with -/// Bluetooth and negotiating up to WiFi if available. It also allows this -/// class to be subclassed by any interfaces that don't want to give bytes but -/// want to validate and give out packets. This can be done by overriding: -/// -/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast); -/// -/// Communication inherits from Broadcaster which means it can be used in -/// conjunction with Listener to wait for multiple broadcaster objects and -/// multiple events from each of those objects. Communication defines a set of -/// pre-defined event bits (see enumerations definitions that start with -/// "eBroadcastBit" below). -/// -/// There are two modes in which communications can occur: -/// \li single-threaded -/// \li multi-threaded -/// -/// In single-threaded mode, all reads and writes happen synchronously on the -/// calling thread. -/// -/// In multi-threaded mode, a read thread is spawned that continually reads -/// data and caches any received bytes. To start the read thread clients call: -/// -/// bool Communication::StartReadThread (Status *); -/// -/// If true is returned a read thread has been spawned that will continually -/// execute a call to the pure virtual DoRead function: -/// -/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); +/// Bluetooth and negotiating up to WiFi if available. /// -/// When bytes are received the data gets cached in \a m_bytes and this class -/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that -/// want packet based communication should override AppendBytesToCache. The -/// subclasses can choose to call the built in AppendBytesToCache with the \a -/// broadcast parameter set to false. This will cause the \b -/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the -/// subclass can post a \b eBroadcastBitPacketAvailable event when a full -/// packet of data has been received. -/// -/// If the connection is disconnected a \b eBroadcastBitDisconnected event -/// gets broadcast. If the read thread exits a \b -/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also -/// post a \b eBroadcastBitReadThreadShouldExit event to this object which -/// will cause the read thread to exit. -class Communication : public Broadcaster { +/// When using this class, all reads and writes happen synchronously on the +/// calling thread. There is also a ThreadedCommunication class that supports +/// multi-threaded mode. +class Communication { public: - FLAGS_ANONYMOUS_ENUM(){ - eBroadcastBitDisconnected = - (1u << 0), ///< Sent when the communications connection is lost. - eBroadcastBitReadThreadGotBytes = - (1u << 1), ///< Sent by the read thread when bytes become available. - eBroadcastBitReadThreadDidExit = - (1u - << 2), ///< Sent by the read thread when it exits to inform clients. - eBroadcastBitReadThreadShouldExit = - (1u << 3), ///< Sent by clients that need to cancel the read thread. - eBroadcastBitPacketAvailable = - (1u << 4), ///< Sent when data received makes a complete packet. - eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread - ///to indicate all pending - ///input has been processed. - kLoUserBroadcastBit = - (1u << 16), ///< Subclasses can used bits 31:16 for any needed events. - kHiUserBroadcastBit = (1u << 31), - eAllEventBits = 0xffffffff}; - - 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. - /// - /// \param[in] broadcaster_name - /// The name of the broadcaster object. This name should be as - /// complete as possible to uniquely identify this object. The - /// broadcaster name can be updated after the connect function - /// is called. - Communication(const char *broadcaster_name); + /// Construct the Communication object. + Communication(); /// Destructor. /// /// The destructor is virtual since this class gets subclassed. - ~Communication() override; + virtual ~Communication(); - void Clear(); + virtual void Clear(); /// Connect using the current connection by passing \a url to its connect /// function. string. @@ -148,7 +73,7 @@ public: /// /// \see Status& Communication::GetError (); /// \see bool Connection::Disconnect (); - lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr); + virtual lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr); /// Check if the connection is valid. /// @@ -166,13 +91,6 @@ public: /// If no read thread is running, this function call the connection's /// Connection::Read(...) function to get any available. /// - /// If a read thread has been started, this function will check for any - /// cached bytes that have already been read and return any currently - /// available bytes. If no bytes are cached, it will wait for the bytes to - /// become available by listening for the \a eBroadcastBitReadThreadGotBytes - /// event. If this function consumes all of the bytes in the cache, it will - /// reset the \a eBroadcastBitReadThreadGotBytes event bit. - /// /// \param[in] dst /// A destination buffer that must be at least \a dst_len bytes /// long. @@ -182,14 +100,15 @@ public: /// number of bytes that can be placed into \a dst. /// /// \param[in] timeout - /// A timeout value or llvm::None for no timeout. + /// A timeout value or std::nullopt for no timeout. /// /// \return /// The number of bytes actually read. /// /// \see size_t Connection::Read (void *, size_t); - size_t Read(void *dst, size_t dst_len, const Timeout &timeout, - lldb::ConnectionStatus &status, Status *error_ptr); + virtual size_t Read(void *dst, size_t dst_len, + const Timeout &timeout, + lldb::ConnectionStatus &status, Status *error_ptr); /// The actual write function that attempts to write to the communications /// protocol. @@ -209,6 +128,22 @@ public: size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr); + /// Repeatedly attempt writing until either \a src_len bytes are written + /// or a permanent failure occurs. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to attempt to write, and also the + /// number of bytes are currently available in \a src. + /// + /// \return + /// The number of bytes actually Written. + size_t WriteAll(const void *src, size_t src_len, + lldb::ConnectionStatus &status, Status *error_ptr); + /// Sets the connection that it to be used by this class. /// /// By making a communication class that uses different connections it @@ -221,69 +156,7 @@ public: /// /// \see /// class Connection - void SetConnection(std::unique_ptr connection); - - /// Starts a read thread whose sole purpose it to read bytes from the - /// current connection. This function will call connection's read function: - /// - /// size_t Connection::Read (void *, size_t); - /// - /// When bytes are read and cached, this function will call: - /// - /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, - /// bool - /// broadcast); - /// - /// Subclasses should override this function if they wish to override the - /// default action of caching the bytes and broadcasting a \b - /// eBroadcastBitReadThreadGotBytes event. - /// - /// \return - /// \b True if the read thread was successfully started, \b - /// false otherwise. - /// - /// \see size_t Connection::Read (void *, size_t); - /// \see void Communication::AppendBytesToCache (const uint8_t * bytes, - /// size_t len, bool broadcast); - virtual bool StartReadThread(Status *error_ptr = nullptr); - - /// Stops the read thread by cancelling it. - /// - /// \return - /// \b True if the read thread was successfully canceled, \b - /// false otherwise. - virtual bool StopReadThread(Status *error_ptr = nullptr); - - virtual bool JoinReadThread(Status *error_ptr = nullptr); - /// Checks if there is a currently running read thread. - /// - /// \return - /// \b True if the read thread is running, \b false otherwise. - bool ReadThreadIsRunning(); - - /// The static read thread function. This function will call the "DoRead" - /// function continuously and wait for data to become available. When data - /// is received it will append the available data to the internal cache and - /// broadcast a \b eBroadcastBitReadThreadGotBytes event. - /// - /// \param[in] comm_ptr - /// A pointer to an instance of this class. - /// - /// \return - /// \b NULL. - /// - /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); - static lldb::thread_result_t ReadThread(lldb::thread_arg_t comm_ptr); - - void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, - void *callback_baton); - - /// Wait for the read thread to process all outstanding data. - /// - /// After this function returns, the read thread has processed all data that - /// has been waiting in the Connection queue. - /// - void SynchronizeWithReadThread(); + virtual void SetConnection(std::unique_ptr connection); static std::string ConnectionStatusAsString(lldb::ConnectionStatus status); @@ -291,73 +164,17 @@ public: void SetCloseOnEOF(bool b) { m_close_on_eof = b; } - static ConstString &GetStaticBroadcasterClass(); - - ConstString &GetBroadcasterClass() const override { - return GetStaticBroadcasterClass(); - } - 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. - std::atomic m_read_thread_enabled; - std::atomic m_read_thread_did_exit; - std::string - m_bytes; ///< A buffer to cache bytes read in the ReadThread function. - std::recursive_mutex m_bytes_mutex; ///< A mutex to protect multi-threaded - ///access to the cached bytes. std::mutex m_write_mutex; ///< Don't let multiple threads write at the same time... - std::mutex m_synchronize_mutex; - ReadThreadBytesReceived m_callback; - void *m_callback_baton; bool m_close_on_eof; size_t ReadFromConnection(void *dst, size_t dst_len, const Timeout &timeout, lldb::ConnectionStatus &status, Status *error_ptr); - /// Append new bytes that get read from the read thread into the internal - /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes - /// event to be broadcast if \a broadcast is true. - /// - /// Subclasses can override this function in order to inspect the received - /// data and check if a packet is available. - /// - /// Subclasses can also still call this function from the overridden method - /// to allow the caching to correctly happen and suppress the broadcasting - /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast - /// to false. - /// - /// \param[in] src - /// A source buffer that must be at least \a src_len bytes - /// long. - /// - /// \param[in] src_len - /// The number of bytes to append to the cache. - virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, - bool broadcast, - lldb::ConnectionStatus status); - - /// Get any available bytes from our data cache. If this call empties the - /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset - /// to signify no more bytes are available. - /// - /// \param[in] dst - /// A destination buffer that must be at least \a dst_len bytes - /// long. - /// - /// \param[in] dst_len - /// The number of bytes to attempt to read from the cache, - /// and also the max number of bytes that can be placed into - /// \a dst. - /// - /// \return - /// The number of bytes extracted from the data cache. - size_t GetCachedBytes(void *dst, size_t dst_len); - private: Communication(const Communication &) = delete; const Communication &operator=(const Communication &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Core/DataFileCache.h b/gnu/llvm/lldb/include/lldb/Core/DataFileCache.h new file mode 100644 index 00000000000..8a233afaff3 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Core/DataFileCache.h @@ -0,0 +1,228 @@ +//===-- DataFileCache.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_CORE_DATAFILECACHE_H +#define LLDB_CORE_DATAFILECACHE_H + +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UUID.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/CachePruning.h" +#include "llvm/Support/Caching.h" +#include "llvm/Support/MemoryBuffer.h" + +#include +#include + +namespace lldb_private { + +/// This class enables data to be cached into a directory using the llvm +/// caching code. Data can be stored and accessed using a unique string key. +/// The data will be stored in the directory that is specified in the +/// DataFileCache constructor. The data will be stored in files that start with +/// "llvmcache-" where is the key name specified when getting to +/// setting cached data. +/// +/// Sample code for how to use the cache: +/// +/// DataFileCache cache("/tmp/lldb-test-cache"); +/// StringRef key("Key1"); +/// auto mem_buffer_up = cache.GetCachedData(key); +/// if (mem_buffer_up) { +/// printf("cached data:\n%s", mem_buffer_up->getBufferStart()); +/// } else { +/// std::vector data = { 'h', 'e', 'l', 'l', 'o', '\n' }; +/// cache.SetCachedData(key, data); +/// } + +class DataFileCache { +public: + /// Create a data file cache in the directory path that is specified, using + /// the specified policy. + /// + /// Data will be cached in files created in this directory when clients call + /// DataFileCache::SetCacheData. + DataFileCache(llvm::StringRef path, + llvm::CachePruningPolicy policy = + DataFileCache::GetLLDBIndexCachePolicy()); + + /// Gets the default LLDB index cache policy, which is controlled by the + /// "LLDBIndexCache" family of settings. + static llvm::CachePruningPolicy GetLLDBIndexCachePolicy(); + + /// Get cached data from the cache directory for the specified key. + /// + /// Keys must be unique for any given data. This function attempts to see if + /// the data is available for the specified key and will return a valid memory + /// buffer is data is available. + /// + /// \param key + /// The unique string key that identifies data being cached. + /// + /// \return + /// A valid unique pointer to a memory buffer if the data is available, or + /// a unique pointer that contains NULL if the data is not available. + std::unique_ptr GetCachedData(llvm::StringRef key); + + /// Set cached data for the specified key. + /// + /// Setting the cached data will save a file in the cache directory to contain + /// the specified data. + /// + /// \param key + /// The unique string key that identifies data being cached. + /// + /// \return + /// True if the data was successfully cached, false otherwise. + bool SetCachedData(llvm::StringRef key, llvm::ArrayRef data); + + /// Remove the cache file associated with the key. + Status RemoveCacheFile(llvm::StringRef key); + +private: + /// Return the cache file that is associated with the key. + FileSpec GetCacheFilePath(llvm::StringRef key); + + llvm::FileCache m_cache_callback; + FileSpec m_cache_dir; + std::mutex m_mutex; + std::unique_ptr m_mem_buff_up; + bool m_take_ownership = false; +}; + +/// A signature for a given file on disk. +/// +/// Any files that are cached in the LLDB index cached need some data that +/// uniquely identifies a file on disk and this information should be written +/// into each cache file so we can validate if the cache file still matches +/// the file we are trying to load cached data for. Objects can fill out this +/// signature and then encode and decode them to validate the signatures +/// match. If they do not match, the cache file on disk should be removed as +/// it is out of date. +struct CacheSignature { + /// UUID of object file or module. + std::optional m_uuid; + /// Modification time of file on disk. + std::optional m_mod_time; + /// If this describes a .o file with a BSD archive, the BSD archive's + /// modification time will be in m_mod_time, and the .o file's modification + /// time will be in this m_obj_mod_time. + std::optional m_obj_mod_time; + + CacheSignature() = default; + + /// Create a signature from a module. + CacheSignature(lldb_private::Module *module); + + /// Create a signature from an object file. + CacheSignature(lldb_private::ObjectFile *objfile); + + void Clear() { + m_uuid = std::nullopt; + m_mod_time = std::nullopt; + m_obj_mod_time = std::nullopt; + } + + /// Return true only if the CacheSignature is valid. + /// + /// Cache signatures are considered valid only if there is a UUID in the file + /// that can uniquely identify the file. Some build systems play with + /// modification times of file so we can not trust them without using valid + /// unique idenifier like the UUID being valid. + bool IsValid() const { return m_uuid.has_value(); } + + /// Check if two signatures are the same. + bool operator==(const CacheSignature &rhs) const { + return m_uuid == rhs.m_uuid && m_mod_time == rhs.m_mod_time && + m_obj_mod_time == rhs.m_obj_mod_time; + } + + /// Check if two signatures differ. + bool operator!=(const CacheSignature &rhs) const { return !(*this == rhs); } + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. The CacheSignature + /// object must have at least one member variable that has a value in order to + /// be serialized so that we can match this data to when the cached file is + /// loaded at a later time. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \return + /// True if a signature was encoded, and false if there were no member + /// variables that had value. False indicates this data should not be + /// cached to disk because we were unable to encode a valid signature. + bool Encode(DataEncoder &encoder) const; + + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \return + /// True if the signature was successfully decoded, false otherwise. + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr); +}; + +/// Many cache files require string tables to store data efficiently. This +/// class helps create string tables. +class ConstStringTable { +public: + ConstStringTable() = default; + /// Add a string into the string table. + /// + /// Add a string to the string table will only add the same string one time + /// and will return the offset in the string table buffer to that string. + /// String tables are easy to build with ConstString objects since most LLDB + /// classes for symbol or debug info use them already and they provide + /// permanent storage for the string. + /// + /// \param s + /// The string to insert into the string table. + /// + /// \return + /// The byte offset from the start of the string table for the inserted + /// string. Duplicate strings that get inserted will return the same + /// byte offset. + uint32_t Add(ConstString s); + + bool Encode(DataEncoder &encoder); + +private: + std::vector m_strings; + llvm::DenseMap m_string_to_offset; + /// Skip one byte to start the string table off with an empty string. + uint32_t m_next_offset = 1; +}; + +/// Many cache files require string tables to store data efficiently. This +/// class helps give out strings from a string table that was read from a +/// cache file. +class StringTableReader { +public: + StringTableReader() = default; + + llvm::StringRef Get(uint32_t offset) const; + + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr); + +protected: + /// All of the strings in the string table are contained in m_data. + llvm::StringRef m_data; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_DATAFILECACHE_H diff --git a/gnu/llvm/lldb/include/lldb/Core/Debugger.h b/gnu/llvm/lldb/include/lldb/Core/Debugger.h index f0849c9ac95..dd3e6c061fc 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Debugger.h +++ b/gnu/llvm/lldb/include/lldb/Core/Debugger.h @@ -12,8 +12,10 @@ #include #include +#include #include +#include "lldb/Core/DebuggerEvents.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/SourceManager.h" @@ -48,11 +50,14 @@ namespace llvm { class raw_ostream; +class ThreadPool; } namespace lldb_private { class Address; +class CallbackLogHandler; class CommandInterpreter; +class LogHandler; class Process; class Stream; class SymbolContext; @@ -76,6 +81,9 @@ public: /// Broadcaster event bits definitions. enum { eBroadcastBitProgress = (1 << 0), + eBroadcastBitWarning = (1 << 1), + eBroadcastBitError = (1 << 2), + eBroadcastSymbolChange = (1 << 3), }; static ConstString GetStaticBroadcasterClass(); @@ -84,39 +92,6 @@ public: Broadcaster &GetBroadcaster() { return m_broadcaster; } const Broadcaster &GetBroadcaster() const { return m_broadcaster; } - class ProgressEventData : public EventData { - - public: - ProgressEventData(uint64_t progress_id, const std::string &message, - uint64_t completed, uint64_t total, - bool debugger_specific) - : m_message(message), m_id(progress_id), m_completed(completed), - m_total(total), m_debugger_specific(debugger_specific) {} - - static ConstString GetFlavorString(); - - ConstString GetFlavor() const override; - - void Dump(Stream *s) const override; - - static const ProgressEventData * - GetEventDataFromEvent(const Event *event_ptr); - uint64_t GetID() const { return m_id; } - uint64_t GetCompleted() const { return m_completed; } - uint64_t GetTotal() const { return m_total; } - const std::string &GetMessage() const { return m_message; } - bool IsDebuggerSpecific() const { return m_debugger_specific; } - - private: - std::string m_message; - const uint64_t m_id; - uint64_t m_completed; - const uint64_t m_total; - const bool m_debugger_specific; - ProgressEventData(const ProgressEventData &) = delete; - const ProgressEventData &operator=(const ProgressEventData &) = delete; - }; - ~Debugger() override; static lldb::DebuggerSP @@ -176,7 +151,9 @@ public: repro::DataRecorder *GetInputRecorder(); - void SetInputFile(lldb::FileSP file, repro::DataRecorder *recorder = nullptr); + Status SetInputString(const char *data); + + void SetInputFile(lldb::FileSP file); void SetOutputFile(lldb::FileSP file); @@ -197,7 +174,7 @@ public: ScriptInterpreter * GetScriptInterpreter(bool can_create = true, - llvm::Optional language = {}); + std::optional language = {}); lldb::ListenerSP GetListener() { return m_listener_sp; } @@ -266,6 +243,7 @@ public: bool EnableLog(llvm::StringRef channel, llvm::ArrayRef categories, llvm::StringRef log_file, uint32_t log_options, + size_t buffer_size, LogHandlerKind log_handler_kind, llvm::raw_ostream &error_stream); void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton); @@ -300,6 +278,10 @@ public: bool SetScriptLanguage(lldb::ScriptLanguage script_lang); + lldb::LanguageType GetREPLLanguage() const; + + bool SetREPLLanguage(lldb::LanguageType repl_lang); + uint32_t GetTerminalWidth() const; bool SetTerminalWidth(uint32_t term_width); @@ -309,8 +291,6 @@ public: void SetPrompt(llvm::StringRef p); void SetPrompt(const char *) = delete; - llvm::StringRef GetReproducerPath() const; - bool GetUseExternalEditor() const; bool SetUseExternalEditor(bool use_external_editor_p); @@ -319,8 +299,20 @@ public: bool SetUseColor(bool use_color); + bool GetShowProgress() const; + + bool SetShowProgress(bool show_progress); + + llvm::StringRef GetShowProgressAnsiPrefix() const; + + llvm::StringRef GetShowProgressAnsiSuffix() const; + bool GetUseAutosuggestion() const; + llvm::StringRef GetAutosuggestionAnsiPrefix() const; + + llvm::StringRef GetAutosuggestionAnsiSuffix() const; + bool GetUseSourceCache() const; bool SetUseSourceCache(bool use_source_cache); @@ -357,6 +349,8 @@ public: bool SetTabSize(uint32_t tab_size); + lldb::DWIMPrintVerbosity GetDWIMPrintVerbosity() const; + bool GetEscapeNonPrintables() const; bool GetNotifyVoid() const; @@ -387,6 +381,75 @@ public: return m_broadcaster_manager_sp; } + /// Shared thread poll. Use only with ThreadPoolTaskGroup. + static llvm::ThreadPool &GetThreadPool(); + + /// Report warning events. + /// + /// Warning events will be delivered to any debuggers that have listeners + /// for the eBroadcastBitWarning. + /// + /// \param[in] message + /// The warning message to be reported. + /// + /// \param [in] debugger_id + /// If this optional parameter has a value, it indicates the unique + /// debugger identifier that this diagnostic should be delivered to. If + /// this optional parameter does not have a value, the diagnostic event + /// will be delivered to all debuggers. + /// + /// \param [in] once + /// If a pointer is passed to a std::once_flag, then it will be used to + /// ensure the given warning is only broadcast once. + static void + ReportWarning(std::string message, + std::optional debugger_id = std::nullopt, + std::once_flag *once = nullptr); + + /// Report error events. + /// + /// Error events will be delivered to any debuggers that have listeners + /// for the eBroadcastBitError. + /// + /// \param[in] message + /// The error message to be reported. + /// + /// \param [in] debugger_id + /// If this optional parameter has a value, it indicates the unique + /// debugger identifier that this diagnostic should be delivered to. If + /// this optional parameter does not have a value, the diagnostic event + /// will be delivered to all debuggers. + /// + /// \param [in] once + /// If a pointer is passed to a std::once_flag, then it will be used to + /// ensure the given error is only broadcast once. + static void + ReportError(std::string message, + std::optional debugger_id = std::nullopt, + std::once_flag *once = nullptr); + + /// Report info events. + /// + /// Unlike warning and error events, info events are not broadcast but are + /// logged for diagnostic purposes. + /// + /// \param[in] message + /// The info message to be reported. + /// + /// \param [in] debugger_id + /// If this optional parameter has a value, it indicates this diagnostic is + /// associated with a unique debugger instance. + /// + /// \param [in] once + /// If a pointer is passed to a std::once_flag, then it will be used to + /// ensure the given info is only logged once. + static void + ReportInfo(std::string message, + std::optional debugger_id = std::nullopt, + std::once_flag *once = nullptr); + + static void ReportSymbolChange(const ModuleSpec &module_spec); + protected: friend class CommandInterpreter; friend class REPL; @@ -423,14 +486,19 @@ protected: /// delivered to all debuggers. static void ReportProgress(uint64_t progress_id, const std::string &message, uint64_t completed, uint64_t total, - llvm::Optional debugger_id); + std::optional debugger_id); + + static void ReportDiagnosticImpl(DiagnosticEventData::Type type, + std::string message, + std::optional debugger_id, + std::once_flag *once); + + void PrintProgress(const ProgressEventData &data); bool StartEventHandlerThread(); void StopEventHandlerThread(); - static lldb::thread_result_t EventHandlerThread(lldb::thread_arg_t arg); - void PushIOHandler(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler = true); @@ -444,9 +512,9 @@ protected: void JoinIOHandlerThread(); - static lldb::thread_result_t IOHandlerThread(lldb::thread_arg_t arg); + lldb::thread_result_t IOHandlerThread(); - void DefaultEventHandler(); + lldb::thread_result_t DefaultEventHandler(); void HandleBreakpointEvent(const lldb::EventSP &event_sp); @@ -454,6 +522,10 @@ protected: void HandleThreadEvent(const lldb::EventSP &event_sp); + void HandleProgressEvent(const lldb::EventSP &event_sp); + + void HandleDiagnosticEvent(const lldb::EventSP &event_sp); + // Ensures two threads don't attempt to flush process output in parallel. std::mutex m_output_flush_mutex; void FlushProcessOutput(Process &process, bool flush_stdout, @@ -502,8 +574,10 @@ protected: IOHandlerStack m_io_handler_stack; std::recursive_mutex m_io_handler_synchronous_mutex; - llvm::StringMap> m_log_streams; - std::shared_ptr m_log_callback_stream_sp; + std::optional m_current_event_id; + + llvm::StringMap> m_stream_handlers; + std::shared_ptr m_callback_handler_sp; ConstString m_instance_name; static LoadPluginCallbackType g_load_plugin_callback; typedef std::vector LoadedPluginsList; diff --git a/gnu/llvm/lldb/include/lldb/Core/DebuggerEvents.h b/gnu/llvm/lldb/include/lldb/Core/DebuggerEvents.h new file mode 100644 index 00000000000..f2e23a94e61 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Core/DebuggerEvents.h @@ -0,0 +1,111 @@ +//===-- DebuggerEvents.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Event.h" + +#include + +#ifndef LLDB_CORE_DEBUGGER_EVENTS_H +#define LLDB_CORE_DEBUGGER_EVENTS_H + +namespace lldb_private { +class Stream; + +class ProgressEventData : public EventData { +public: + ProgressEventData(uint64_t progress_id, const std::string &message, + uint64_t completed, uint64_t total, bool debugger_specific) + : m_message(message), m_id(progress_id), m_completed(completed), + m_total(total), m_debugger_specific(debugger_specific) {} + + static ConstString GetFlavorString(); + + ConstString GetFlavor() const override; + + void Dump(Stream *s) const override; + + static const ProgressEventData *GetEventDataFromEvent(const Event *event_ptr); + uint64_t GetID() const { return m_id; } + bool IsFinite() const { return m_total != UINT64_MAX; } + uint64_t GetCompleted() const { return m_completed; } + uint64_t GetTotal() const { return m_total; } + const std::string &GetMessage() const { return m_message; } + bool IsDebuggerSpecific() const { return m_debugger_specific; } + +private: + std::string m_message; + const uint64_t m_id; + uint64_t m_completed; + const uint64_t m_total; + const bool m_debugger_specific; + ProgressEventData(const ProgressEventData &) = delete; + const ProgressEventData &operator=(const ProgressEventData &) = delete; +}; + +class DiagnosticEventData : public EventData { +public: + enum class Type { + Info, + Warning, + Error, + }; + DiagnosticEventData(Type type, std::string message, bool debugger_specific) + : m_message(std::move(message)), m_type(type), + m_debugger_specific(debugger_specific) {} + ~DiagnosticEventData() override = default; + + const std::string &GetMessage() const { return m_message; } + bool IsDebuggerSpecific() const { return m_debugger_specific; } + Type GetType() const { return m_type; } + + llvm::StringRef GetPrefix() const; + + void Dump(Stream *s) const override; + + static ConstString GetFlavorString(); + ConstString GetFlavor() const override; + + static const DiagnosticEventData * + GetEventDataFromEvent(const Event *event_ptr); + +protected: + std::string m_message; + Type m_type; + const bool m_debugger_specific; + + DiagnosticEventData(const DiagnosticEventData &) = delete; + const DiagnosticEventData &operator=(const DiagnosticEventData &) = delete; +}; + +class SymbolChangeEventData : public EventData { +public: + SymbolChangeEventData(lldb::DebuggerWP debugger_wp, ModuleSpec module_spec) + : m_debugger_wp(debugger_wp), m_module_spec(std::move(module_spec)) {} + + static ConstString GetFlavorString(); + ConstString GetFlavor() const override; + + static const SymbolChangeEventData * + GetEventDataFromEvent(const Event *event_ptr); + + void DoOnRemoval(Event *event_ptr) override; + +private: + lldb::DebuggerWP m_debugger_wp; + ModuleSpec m_module_spec; + + SymbolChangeEventData(const SymbolChangeEventData &) = delete; + const SymbolChangeEventData & + operator=(const SymbolChangeEventData &) = delete; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_DEBUGGER_EVENTS_H diff --git a/gnu/llvm/lldb/include/lldb/Core/Declaration.h b/gnu/llvm/lldb/include/lldb/Core/Declaration.h index f81de21bc8f..4a0e9047b54 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Declaration.h +++ b/gnu/llvm/lldb/include/lldb/Core/Declaration.h @@ -24,7 +24,7 @@ namespace lldb_private { class Declaration { public: /// Default constructor. - Declaration() : m_file() {} + Declaration() = default; /// Construct with file specification, and optional line and column. /// @@ -45,7 +45,7 @@ public: /// Construct with a pointer to another Declaration object. Declaration(const Declaration *decl_ptr) - : m_file(), m_line(0), m_column(LLDB_INVALID_COLUMN_NUMBER) { + : m_line(0), m_column(LLDB_INVALID_COLUMN_NUMBER) { if (decl_ptr) *this = *decl_ptr; } @@ -152,8 +152,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Set accessor for the declaration file specification. diff --git a/gnu/llvm/lldb/include/lldb/Core/Disassembler.h b/gnu/llvm/lldb/include/lldb/Core/Disassembler.h index 622c23ff649..b9ac0a5bca3 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Disassembler.h +++ b/gnu/llvm/lldb/include/lldb/Core/Disassembler.h @@ -79,6 +79,15 @@ public: return m_comment.c_str(); } + /// \return + /// The control flow kind of this instruction, or + /// eInstructionControlFlowKindUnknown if the instruction + /// can't be classified. + virtual lldb::InstructionControlFlowKind + GetControlFlowKind(const ExecutionContext *exe_ctx) { + return lldb::eInstructionControlFlowKindUnknown; + } + virtual void CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0; @@ -105,6 +114,9 @@ public: /// \param[in] show_bytes /// Whether the bytes of the assembly instruction should be printed. /// + /// \param[in] show_control_flow_kind + /// Whether the control flow kind of the instruction should be printed. + /// /// \param[in] max_opcode_byte_size /// The size (in bytes) of the largest instruction in the list that /// we are printing (for text justification/alignment purposes) @@ -140,7 +152,8 @@ 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, bool show_address, - bool show_bytes, const ExecutionContext *exe_ctx, + bool show_bytes, bool show_control_flow_kind, + const ExecutionContext *exe_ctx, const SymbolContext *sym_ctx, const SymbolContext *prev_sym_ctx, const FormatEntity::Entry *disassembly_addr_format, @@ -150,6 +163,10 @@ public: virtual bool HasDelaySlot(); + virtual bool IsLoad() = 0; + + virtual bool IsAuthenticated() = 0; + bool CanSetBreakpoint (); virtual size_t Decode(const Disassembler &disassembler, @@ -209,6 +226,9 @@ public: virtual bool IsCall() { return false; } + static const char *GetNameForInstructionControlFlowKind( + lldb::InstructionControlFlowKind instruction_control_flow_kind); + protected: Address m_address; // The section offset address of this instruction // We include an address class in the Instruction class to @@ -316,7 +336,7 @@ public: void Append(lldb::InstructionSP &inst_sp); void Dump(Stream *s, bool show_address, bool show_bytes, - const ExecutionContext *exe_ctx); + bool show_control_flow_kind, const ExecutionContext *exe_ctx); private: typedef std::vector collection; @@ -336,6 +356,10 @@ public: bool HasDelaySlot() override; + bool IsLoad() override; + + bool IsAuthenticated() override; + void CalculateMnemonicOperandsAndComment( const ExecutionContext *exe_ctx) override { // TODO: fill this in and put opcode name into Instruction::m_opcode_name, @@ -367,7 +391,8 @@ public: eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains // the current PC (mixed mode only) eOptionMarkPCAddress = - (1u << 3) // Mark the disassembly line the contains the PC + (1u << 3), // Mark the disassembly line the contains the PC + eOptionShowControlFlowKind = (1u << 4), }; enum HexImmediateStyle { @@ -457,7 +482,7 @@ protected: uint32_t line = LLDB_INVALID_LINE_NUMBER; uint32_t column = 0; - SourceLine() : file() {} + SourceLine() = default; bool operator==(const SourceLine &rhs) const { return file == rhs.file && line == rhs.line && rhs.column == column; @@ -481,7 +506,7 @@ protected: // Whether to print a blank line at the end of the source lines. bool print_source_context_end_eol = true; - SourceLinesToDisplay() : lines() {} + SourceLinesToDisplay() = default; }; // Get the function's declaration line number, hopefully a line number diff --git a/gnu/llvm/lldb/include/lldb/Core/DumpDataExtractor.h b/gnu/llvm/lldb/include/lldb/Core/DumpDataExtractor.h index 12188609e8c..08501b512a2 100644 --- a/gnu/llvm/lldb/include/lldb/Core/DumpDataExtractor.h +++ b/gnu/llvm/lldb/include/lldb/Core/DumpDataExtractor.h @@ -76,6 +76,15 @@ class Stream; /// same integer value. If the items being displayed are not /// bitfields, this value should be zero. /// +/// \param[in] exe_scope +/// If provided, this will be used to lookup language specific +/// information, address information and memory tags. +/// (if they are requested by the other options) +/// +/// \param[in] show_memory_tags +/// If exe_scope and base_addr are valid, include memory tags +/// in the output. This does not apply to certain formats. +/// /// \return /// The offset at which dumping ended. lldb::offset_t @@ -83,7 +92,8 @@ DumpDataExtractor(const DataExtractor &DE, 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); + ExecutionContextScope *exe_scope = nullptr, + bool show_memory_tags = false); void DumpHexBytes(Stream *s, const void *src, size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr); diff --git a/gnu/llvm/lldb/include/lldb/Core/DumpRegisterValue.h b/gnu/llvm/lldb/include/lldb/Core/DumpRegisterValue.h index 443fdb34266..08bf0af8f36 100644 --- a/gnu/llvm/lldb/include/lldb/Core/DumpRegisterValue.h +++ b/gnu/llvm/lldb/include/lldb/Core/DumpRegisterValue.h @@ -14,16 +14,18 @@ namespace lldb_private { +class ExecutionContextScope; class RegisterValue; struct RegisterInfo; class Stream; // The default value of 0 for reg_name_right_align_at means no alignment at // all. -bool DumpRegisterValue(const RegisterValue ®_val, Stream *s, +void DumpRegisterValue(const RegisterValue ®_val, Stream *s, const RegisterInfo *reg_info, bool prefix_with_name, bool prefix_with_alt_name, lldb::Format format, - uint32_t reg_name_right_align_at = 0); + uint32_t reg_name_right_align_at = 0, + ExecutionContextScope *exe_scope = nullptr); } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Core/EmulateInstruction.h b/gnu/llvm/lldb/include/lldb/Core/EmulateInstruction.h index f50fee095a8..6d76380ce65 100644 --- a/gnu/llvm/lldb/include/lldb/Core/EmulateInstruction.h +++ b/gnu/llvm/lldb/include/lldb/Core/EmulateInstruction.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_EMULATEINSTRUCTION_H #define LLDB_CORE_EMULATEINSTRUCTION_H +#include #include #include "lldb/Core/Address.h" @@ -179,12 +180,17 @@ public: eInfoTypeISAAndImmediateSigned, eInfoTypeISA, eInfoTypeNoArgs - } InfoType; + }; struct Context { ContextType type = eContextInvalid; + + private: enum InfoType info_type = eInfoTypeNoArgs; - union { + + public: + enum InfoType GetInfoType() const { return info_type; } + union ContextInfo { struct RegisterPlusOffset { RegisterInfo reg; // base register int64_t signed_offset; // signed offset added to base register @@ -236,6 +242,8 @@ public: uint32_t isa; } info; + static_assert(std::is_trivial::value, + "ContextInfo must be trivial."); Context() = default; @@ -370,8 +378,8 @@ public: virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; - virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, - RegisterInfo ®_info) = 0; + virtual std::optional + GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) = 0; // Optional overrides virtual bool SetInstruction(const Opcode &insn_opcode, @@ -383,16 +391,16 @@ public: uint32_t reg_num, std::string ®_name); // RegisterInfo variants - bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value); + std::optional ReadRegister(const RegisterInfo ®_info); - uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, + uint64_t ReadRegisterUnsigned(const RegisterInfo ®_info, uint64_t fail_value, bool *success_ptr); - bool WriteRegister(const Context &context, const RegisterInfo *ref_info, + bool WriteRegister(const Context &context, const RegisterInfo &ref_info, const RegisterValue ®_value); bool WriteRegisterUnsigned(const Context &context, - const RegisterInfo *reg_info, uint64_t reg_value); + const RegisterInfo ®_info, uint64_t reg_value); // Register kind and number variants bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, diff --git a/gnu/llvm/lldb/include/lldb/Core/FileSpecList.h b/gnu/llvm/lldb/include/lldb/Core/FileSpecList.h index cab8e9b9b43..a5720d85e7c 100644 --- a/gnu/llvm/lldb/include/lldb/Core/FileSpecList.h +++ b/gnu/llvm/lldb/include/lldb/Core/FileSpecList.h @@ -116,6 +116,32 @@ public: /// else UINT32_MAX is returned. size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; + /// Find a compatible file index. + /// + /// Find the index of a compatible file in the file spec list that matches \a + /// file starting \a idx entries into the file spec list. A file is considered + /// compatible if: + /// - The file matches exactly (only filename if \a file has no directory) + /// - If \a file is relative and any file in the list has this same suffix + /// - If any file in the list is relative and the relative path is a suffix + /// of \a file + /// + /// This is used to implement better matching for setting breakpoints in + /// source files where an IDE might specify a full path when setting the + /// breakpoint and debug info contains relative paths, if a user specifies + /// a relative path when setting a breakpoint. + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \param[in] file + /// The file specification to search for. + /// + /// \return + /// The index of the file that matches \a file if it is found, + /// else UINT32_MAX is returned. + size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const; + /// Get file at index. /// /// Gets a file from the file list. If \a idx is not a valid index, an empty @@ -152,8 +178,6 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; bool IsEmpty() const { return m_files.empty(); } diff --git a/gnu/llvm/lldb/include/lldb/Core/FormatEntity.h b/gnu/llvm/lldb/include/lldb/Core/FormatEntity.h index ecae8500df4..a4972be514c 100644 --- a/gnu/llvm/lldb/include/lldb/Core/FormatEntity.h +++ b/gnu/llvm/lldb/include/lldb/Core/FormatEntity.h @@ -148,7 +148,7 @@ public: Entry(Type t = Type::Invalid, const char *s = nullptr, const char *f = nullptr) - : string(s ? s : ""), printf_format(f ? f : ""), children(), type(t) {} + : string(s ? s : ""), printf_format(f ? f : ""), type(t) {} Entry(llvm::StringRef s); Entry(char ch); @@ -241,6 +241,17 @@ public: llvm::StringRef elements, llvm::StringRef element_format); + /// For each variable in 'args' this function writes the variable + /// name and it's pretty-printed value representation to 'out_stream' + /// in following format: + /// + /// \verbatim + /// name_1=repr_1, name_2=repr_2 ... + /// \endverbatim + static void PrettyPrintFunctionArguments(Stream &out_stream, + VariableList const &args, + ExecutionContextScope *exe_scope); + protected: static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, uint32_t depth); diff --git a/gnu/llvm/lldb/include/lldb/Core/Highlighter.h b/gnu/llvm/lldb/include/lldb/Core/Highlighter.h index b138e57af41..58ecd37180e 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Highlighter.h +++ b/gnu/llvm/lldb/include/lldb/Core/Highlighter.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_HIGHLIGHTER_H #define LLDB_CORE_HIGHLIGHTER_H +#include #include #include @@ -112,12 +113,12 @@ public: /// The stream to which the highlighted version of the user string should /// be written. virtual void Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional cursor_pos, + std::optional cursor_pos, llvm::StringRef previous_lines, Stream &s) const = 0; /// Utility method for calling Highlight without a stream. std::string Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional cursor_pos, + std::optional cursor_pos, llvm::StringRef previous_lines = "") const; }; @@ -128,7 +129,7 @@ public: llvm::StringRef GetName() const override { return "none"; } void Highlight(const HighlightStyle &options, llvm::StringRef line, - llvm::Optional cursor_pos, + std::optional cursor_pos, llvm::StringRef previous_lines, Stream &s) const override; }; diff --git a/gnu/llvm/lldb/include/lldb/Core/IOHandler.h b/gnu/llvm/lldb/include/lldb/Core/IOHandler.h index 4a3b788e3ea..18d87acbd87 100644 --- a/gnu/llvm/lldb/include/lldb/Core/IOHandler.h +++ b/gnu/llvm/lldb/include/lldb/Core/IOHandler.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -31,10 +32,7 @@ namespace lldb_private { class Debugger; -namespace repro { -class DataRecorder; -} -} +} // namespace lldb_private namespace curses { class Application; @@ -63,8 +61,7 @@ public: IOHandler(Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, uint32_t flags, - repro::DataRecorder *data_recorder); + const lldb::StreamFileSP &error_sp, uint32_t flags); virtual ~IOHandler(); @@ -85,11 +82,11 @@ public: virtual void GotEOF() = 0; - virtual bool IsActive() { return m_active && !m_done; } + bool IsActive() { return m_active && !m_done; } - virtual void SetIsDone(bool b) { m_done = b; } + void SetIsDone(bool b) { m_done = b; } - virtual bool GetIsDone() { return m_done; } + bool GetIsDone() { return m_done; } Type GetType() const { return m_type; } @@ -163,17 +160,16 @@ public: void WaitForPop(); - virtual void PrintAsync(Stream *stream, const char *s, size_t len) { - stream->Write(s, len); - stream->Flush(); - } + virtual void PrintAsync(const char *s, size_t len, bool is_stdout); + + std::recursive_mutex &GetOutputMutex() { return m_output_mutex; } protected: Debugger &m_debugger; lldb::FileSP m_input_sp; lldb::StreamFileSP m_output_sp; lldb::StreamFileSP m_error_sp; - repro::DataRecorder *m_data_recorder; + std::recursive_mutex m_output_mutex; Predicate m_popped; Flags m_flags; Type m_type; @@ -205,8 +201,8 @@ public: virtual void IOHandlerDeactivated(IOHandler &io_handler) {} - virtual llvm::Optional IOHandlerSuggestion(IOHandler &io_handler, - llvm::StringRef line); + virtual std::optional IOHandlerSuggestion(IOHandler &io_handler, + llvm::StringRef line); virtual void IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request); @@ -338,8 +334,7 @@ public: uint32_t line_number_start, // If non-zero show line numbers // starting at // 'line_number_start' - IOHandlerDelegate &delegate, - repro::DataRecorder *data_recorder); + IOHandlerDelegate &delegate); IOHandlerEditline(Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp, @@ -351,8 +346,7 @@ public: uint32_t line_number_start, // If non-zero show line numbers // starting at // 'line_number_start' - IOHandlerDelegate &delegate, - repro::DataRecorder *data_recorder); + IOHandlerDelegate &delegate); IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, const char *, bool, bool, uint32_t, @@ -415,7 +409,7 @@ public: uint32_t GetCurrentLineIndex() const; - void PrintAsync(Stream *stream, const char *s, size_t len) override; + void PrintAsync(const char *s, size_t len, bool is_stdout) override; private: #if LLDB_ENABLE_LIBEDIT @@ -424,7 +418,7 @@ private: int FixIndentationCallback(Editline *editline, const StringList &lines, int cursor_position); - llvm::Optional SuggestionCallback(llvm::StringRef line); + std::optional SuggestionCallback(llvm::StringRef line); void AutoCompleteCallback(CompletionRequest &request); #endif @@ -442,8 +436,6 @@ protected: bool m_multi_line; bool m_color_prompts; bool m_interrupt_exits; - bool m_editing; // Set to true when fetching a line manually (not using - // libedit) std::string m_line_buffer; }; @@ -542,7 +534,7 @@ public: return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr); } - void PrintAsync(Stream *stream, const char *s, size_t len); + bool PrintAsync(const char *s, size_t len, bool is_stdout); protected: typedef std::vector collection; diff --git a/gnu/llvm/lldb/include/lldb/Core/LoadedModuleInfoList.h b/gnu/llvm/lldb/include/lldb/Core/LoadedModuleInfoList.h index ad6da2bd755..537a2b0f1d3 100644 --- a/gnu/llvm/lldb/include/lldb/Core/LoadedModuleInfoList.h +++ b/gnu/llvm/lldb/include/lldb/Core/LoadedModuleInfoList.h @@ -95,13 +95,13 @@ public: protected: bool m_has[e_num]; std::string m_name; - lldb::addr_t m_link_map; - lldb::addr_t m_base; - bool m_base_is_offset; - lldb::addr_t m_dynamic; + lldb::addr_t m_link_map = LLDB_INVALID_ADDRESS; + lldb::addr_t m_base = LLDB_INVALID_ADDRESS; + bool m_base_is_offset = false; + lldb::addr_t m_dynamic = LLDB_INVALID_ADDRESS; }; - LoadedModuleInfoList() : m_list() {} + LoadedModuleInfoList() = default; void add(const LoadedModuleInfo &mod) { m_list.push_back(mod); } diff --git a/gnu/llvm/lldb/include/lldb/Core/Mangled.h b/gnu/llvm/lldb/include/lldb/Core/Mangled.h index d11d13b63cf..dcaa7a8cda6 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Mangled.h +++ b/gnu/llvm/lldb/include/lldb/Core/Mangled.h @@ -12,9 +12,8 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" - +#include "lldb/lldb-types.h" #include "lldb/Utility/ConstString.h" - #include "llvm/ADT/StringRef.h" #include @@ -27,7 +26,7 @@ namespace lldb_private { /// /// Designed to handle mangled names. The demangled version of any names will /// be computed when the demangled name is accessed through the Demangled() -/// acccessor. This class can also tokenize the demangled version of the name +/// accessor. This class can also tokenize the demangled version of the name /// for powerful searches. Functions and symbols could make instances of this /// class for their mangled names. Uniqued string pools are used for the /// mangled, demangled, and token string values to allow for faster @@ -44,7 +43,8 @@ public: eManglingSchemeNone = 0, eManglingSchemeMSVC, eManglingSchemeItanium, - eManglingSchemeRustV0 + eManglingSchemeRustV0, + eManglingSchemeD }; /// Default constructor. @@ -63,37 +63,30 @@ public: explicit Mangled(llvm::StringRef name); - /// Convert to pointer operator. - /// - /// This allows code to check a Mangled object to see if it contains a valid - /// mangled name using code such as: - /// - /// \code - /// Mangled mangled(...); - /// if (mangled) - /// { ... - /// \endcode - /// - /// \return - /// A pointer to this object if either the mangled or unmangled - /// name is set, NULL otherwise. - operator void *() const; + bool operator==(const Mangled &rhs) const { + return m_mangled == rhs.m_mangled && + GetDemangledName() == rhs.GetDemangledName(); + } - /// Logical NOT operator. + bool operator!=(const Mangled &rhs) const { + return !(*this == rhs); + } + + /// Convert to bool operator. /// - /// This allows code to check a Mangled object to see if it contains an - /// empty mangled name using code such as: + /// This allows code to check any Mangled objects to see if they contain + /// anything valid using code such as: /// /// \code /// Mangled mangled(...); - /// if (!mangled) + /// if (mangled) /// { ... /// \endcode /// /// \return - /// Returns \b true if the object has an empty mangled and - /// unmangled name, \b false otherwise. - bool operator!() const; + /// Returns \b true if either the mangled or unmangled name is set, + /// \b false if the object has an empty mangled and unmangled name. + explicit operator bool() const; /// Clear the mangled and demangled values. void Clear(); @@ -190,8 +183,6 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Set the string value in this object. @@ -235,10 +226,9 @@ public: /// Function signature for filtering mangled names. using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme); - /// Trigger explicit demangling to obtain rich mangling information. This is - /// optimized for batch processing while populating a name index. To get the - /// pure demangled name string for a single entity, use GetDemangledName() - /// instead. + /// Get rich mangling information. This is optimized for batch processing + /// while populating a name index. To get the pure demangled name string for + /// a single entity, use GetDemangledName() instead. /// /// For names that match the Itanium mangling scheme, this uses LLVM's /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin @@ -257,8 +247,8 @@ public: /// /// \return /// True on success, false otherwise. - bool DemangleWithRichManglingInfo(RichManglingContext &context, - SkipMangledNameFn *skip_mangled_name); + bool GetRichManglingInfo(RichManglingContext &context, + SkipMangledNameFn *skip_mangled_name); /// Try to identify the mangling scheme used. /// \param[in] name @@ -269,6 +259,35 @@ public: /// for s, otherwise the enumerator for the mangling scheme detected. static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name); + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const StringTableReader &strtab); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + void Encode(DataEncoder &encoder, ConstStringTable &strtab) const; + private: /// Mangled member variables. ConstString m_mangled; ///< The mangled version of the name diff --git a/gnu/llvm/lldb/include/lldb/Core/Module.h b/gnu/llvm/lldb/include/lldb/Core/Module.h index dd7100c4616..31f7894178d 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Module.h +++ b/gnu/llvm/lldb/include/lldb/Core/Module.h @@ -16,18 +16,20 @@ #include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/PathMappingList.h" +#include "lldb/Target/Statistics.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" -#include "lldb/Utility/XcodeSDK.h" #include "lldb/Utility/UUID.h" +#include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Chrono.h" @@ -36,6 +38,7 @@ #include #include #include +#include #include #include @@ -57,6 +60,15 @@ class TypeList; class TypeMap; class VariableList; +/// Options used by Module::FindFunctions. This cannot be a nested class +/// because it must be forward-declared in ModuleList.h. +struct ModuleFunctionSearchOptions { + /// Include the symbol table. + bool include_symbols = false; + /// Include inlined functions. + bool include_inlines = false; +}; + /// \class Module Module.h "lldb/Core/Module.h" /// A class that describes an executable image and its associated /// object and symbol files. @@ -75,6 +87,7 @@ class VariableList; class Module : public std::enable_shared_from_this, public SymbolContextScope { public: + class LookupInfo; // Static functions that can track the lifetime of module objects. This is // handy because we might have Module objects that are in shared pointers // that aren't in the global module list (from ModuleList). If this is the @@ -118,7 +131,7 @@ public: Module(const ModuleSpec &module_spec); template - static lldb::ModuleSP CreateModuleFromObjectFile(Args &&... args) { + static lldb::ModuleSP CreateModuleFromObjectFile(Args &&...args) { // Must create a module and place it into a shared pointer before we can // create an object file since it has a std::weak_ptr back to the module, // so we need to control the creation carefully in this static function @@ -245,16 +258,16 @@ public: /// Returns a valid symbol pointer if a symbol was found, /// nullptr otherwise. const Symbol *FindFirstSymbolWithNameAndType( - ConstString name, - lldb::SymbolType symbol_type = lldb::eSymbolTypeAny); + ConstString name, lldb::SymbolType symbol_type = lldb::eSymbolTypeAny); void FindSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, SymbolContextList &sc_list); - void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - SymbolContextList &sc_list); + void FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + SymbolContextList &sc_list, + Mangled::NamePreference mangling_preference = Mangled::ePreferDemangled); /// Find a function symbols in the object file's symbol table. /// @@ -284,6 +297,23 @@ public: /// matches. void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list); + /// Find functions by lookup info. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will be NULL. + /// + /// \param[in] lookup_info + /// The lookup info of the function we are looking for. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindFunctions(const LookupInfo &lookup_info, + const CompilerDeclContext &parent_decl_ctx, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list); + /// Find functions by name. /// /// If the function is an inlined function, it will have a block, @@ -291,7 +321,7 @@ public: /// containing function. If it is not inlined, then the block will be NULL. /// /// \param[in] name - /// The name of the compile unit we are looking for. + /// The name of the function we are looking for. /// /// \param[in] name_type_mask /// A bit mask of bits that indicate what kind of names should @@ -304,8 +334,9 @@ public: /// matches. void FindFunctions(ConstString name, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool symbols_ok, - bool inlines_ok, SymbolContextList &sc_list); + lldb::FunctionNameType name_type_mask, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list); /// Find functions by name. /// @@ -319,8 +350,9 @@ public: /// \param[out] sc_list /// A symbol context list that gets filled in with all of the /// matches. - void FindFunctions(const RegularExpression ®ex, bool symbols_ok, - bool inlines_ok, SymbolContextList &sc_list); + void FindFunctions(const RegularExpression ®ex, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list); /// Find addresses by file/line /// @@ -427,12 +459,13 @@ public: /// /// \param searched_symbol_files /// Prevents one file from being visited multiple times. - void FindTypes(llvm::ArrayRef pattern, LanguageSet languages, - llvm::DenseSet &searched_symbol_files, - TypeMap &types); + void + FindTypes(llvm::ArrayRef pattern, LanguageSet languages, + llvm::DenseSet &searched_symbol_files, + TypeMap &types); - lldb::TypeSP FindFirstType(const SymbolContext &sc, - ConstString type_name, bool exact_match); + lldb::TypeSP FindFirstType(const SymbolContext &sc, ConstString type_name, + bool exact_match); /// Find types by name that are in a namespace. This function is used by the /// expression parser when searches need to happen in an exact namespace @@ -776,35 +809,57 @@ public: const FileSpec &file_spec, uint32_t line, bool check_inlines, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); - void SetFileSpecAndObjectName(const FileSpec &file, - ConstString object_name); + void SetFileSpecAndObjectName(const FileSpec &file, ConstString object_name); bool GetIsDynamicLinkEditor(); - llvm::Expected + llvm::Expected GetTypeSystemForLanguage(lldb::LanguageType language); + /// Call \p callback for each \p TypeSystem in this \p Module. + /// Return true from callback to keep iterating, false to stop iterating. + void ForEachTypeSystem(llvm::function_ref callback); + // 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)). This centralizes code so // that everyone doesn't need to format their error and log messages on their // own and keeps the output a bit more consistent. - void LogMessage(Log *log, const char *format, ...) - __attribute__((format(printf, 3, 4))); + template + void LogMessage(Log *log, const char *format, Args &&...args) { + LogMessage(log, llvm::formatv(format, std::forward(args)...)); + } - void LogMessageVerboseBacktrace(Log *log, const char *format, ...) - __attribute__((format(printf, 3, 4))); + template + void LogMessageVerboseBacktrace(Log *log, const char *format, + Args &&...args) { + LogMessageVerboseBacktrace( + log, llvm::formatv(format, std::forward(args)...)); + } - void ReportWarning(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template + void ReportWarning(const char *format, Args &&...args) { + ReportWarning(llvm::formatv(format, std::forward(args)...)); + } - void ReportError(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template + void ReportError(const char *format, Args &&...args) { + ReportError(llvm::formatv(format, std::forward(args)...)); + } // Only report an error once when the module is first detected to be modified // so we don't spam the console with many messages. - void ReportErrorIfModifyDetected(const char *format, ...) - __attribute__((format(printf, 2, 3))); + template + void ReportErrorIfModifyDetected(const char *format, Args &&...args) { + ReportErrorIfModifyDetected( + llvm::formatv(format, std::forward(args)...)); + } + + void ReportWarningOptimization(std::optional debugger_id); + + void + ReportWarningUnsupportedLanguage(lldb::LanguageType language, + std::optional debugger_id); // Return true if the file backing this module has changed since the module // was originally created since we saved the initial file modification time @@ -853,12 +908,24 @@ public: /// \return /// The newly remapped filespec that is may or may not exist if /// \a path was successfully located. - llvm::Optional RemapSourceFile(llvm::StringRef path) const; + std::optional RemapSourceFile(llvm::StringRef path) const; bool RemapSourceFile(const char *, std::string &) const = delete; /// Update the ArchSpec to a more specific variant. bool MergeArchitecture(const ArchSpec &arch_spec); + /// Accessor for the symbol table parse time metric. + /// + /// The value is returned as a reference to allow it to be updated by the + /// ElapsedTime RAII object. + StatsDuration &GetSymtabParseTime() { return m_symtab_parse_time; } + + /// Accessor for the symbol table index time metric. + /// + /// The value is returned as a reference to allow it to be updated by the + /// ElapsedTime RAII object. + StatsDuration &GetSymtabIndexTime() { return m_symtab_index_time; } + /// \class LookupInfo Module.h "lldb/Core/Module.h" /// A class that encapsulates name lookup information. /// @@ -882,7 +949,7 @@ public: /// correctly. class LookupInfo { public: - LookupInfo() : m_name(), m_lookup_name() {} + LookupInfo() = default; LookupInfo(ConstString name, lldb::FunctionNameType name_type_mask, lldb::LanguageType language); @@ -901,6 +968,12 @@ public: m_name_type_mask = mask; } + lldb::LanguageType GetLanguageType() const { return m_language; } + + bool NameMatchesLookupInfo( + ConstString function_name, + lldb::LanguageType language_type = lldb::eLanguageTypeUnknown) const; + void Prune(SymbolContextList &sc_list, size_t start_idx) const; protected: @@ -922,30 +995,67 @@ public: bool m_match_name_after_lookup = false; }; + /// Get a unique hash for this module. + /// + /// The hash should be enough to identify the file on disk and the + /// architecture of the file. If the module represents an object inside of a + /// file, then the hash should include the object name and object offset to + /// ensure a unique hash. Some examples: + /// - just a regular object file (mach-o, elf, coff, etc) should create a hash + /// - a universal mach-o file that contains to multiple architectures, + /// each architecture slice should have a unique hash even though they come + /// from the same file + /// - a .o file inside of a BSD archive. Each .o file will have an object name + /// and object offset that should produce a unique hash. The object offset + /// is needed as BSD archive files can contain multiple .o files that have + /// the same name. + uint32_t Hash(); + + /// Get a unique cache key for the current module. + /// + /// The cache key must be unique for a file on disk and not change if the file + /// is updated. This allows cache data to use this key as a prefix and as + /// files are modified in disk, we will overwrite the cache files. If one file + /// can contain multiple files, like a universal mach-o file or like a BSD + /// archive, the cache key must contain enough information to differentiate + /// these different files. + std::string GetCacheKey(); + + /// Get the global index file cache. + /// + /// LLDB can cache data for a module between runs. This cache directory can be + /// used to stored data that previously was manually created each time you debug. + /// Examples include debug information indexes, symbol tables, symbol table + /// indexes, and more. + /// + /// \returns + /// If caching is enabled in the lldb settings, return a pointer to the data + /// file cache. If caching is not enabled, return NULL. + static DataFileCache *GetIndexCache(); protected: // Member Variables mutable std::recursive_mutex m_mutex; ///< A mutex to keep this object happy - ///in multi-threaded environments. + /// in multi-threaded environments. /// The modification time for this module when it was created. llvm::sys::TimePoint<> m_mod_time; - ArchSpec m_arch; ///< The architecture for this module. + ArchSpec m_arch; ///< The architecture for this module. UUID m_uuid; ///< Each module is assumed to have a unique identifier to help - ///match it up to debug symbols. + /// match it up to debug symbols. FileSpec m_file; ///< The file representation on disk for this module (if - ///there is one). + /// there is one). FileSpec m_platform_file; ///< The path to the module on the platform on which - ///it is being debugged + /// it is being debugged FileSpec m_remote_install_file; ///< If set when debugging on remote - ///platforms, this module will be installed at - ///this location + /// platforms, this module will be installed + /// at this location FileSpec m_symfile_spec; ///< If this path is valid, then this is the file - ///that _will_ be used as the symbol file for this - ///module + /// that _will_ be used as the symbol file for this + /// module ConstString m_object_name; ///< The name an object within this module that is - ///selected, or empty of the module is represented - ///by \a m_file. + /// selected, or empty of the module is represented + /// by \a m_file. uint64_t m_object_offset = 0; llvm::sys::TimePoint<> m_object_mod_time; @@ -955,20 +1065,20 @@ protected: lldb::DataBufferSP m_data_sp; lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file - ///parser for this module as it may or may - ///not be shared with the SymbolFile - llvm::Optional m_unwind_table; ///< Table of FuncUnwinders - /// objects created for this - /// Module's functions + /// parser for this module as it may or may + /// not be shared with the SymbolFile + std::optional m_unwind_table; ///< Table of FuncUnwinders + /// objects created for this + /// Module's functions lldb::SymbolVendorUP m_symfile_up; ///< A pointer to the symbol vendor for this module. std::vector m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and - ///changes the symbol file, + /// changes the symbol file, ///< we need to keep all old symbol files around in case anyone has type - ///references to them - TypeSystemMap m_type_system_map; ///< A map of any type systems associated - ///with this module + /// references to them + TypeSystemMap m_type_system_map; ///< A map of any type systems associated + /// with this module /// Module specific source remappings for when you have debug info for a /// module that doesn't match where the sources currently are. PathMappingList m_source_mappings = @@ -984,6 +1094,17 @@ protected: mutable bool m_file_has_changed : 1, m_first_file_changed_log : 1; /// See if the module was modified after it /// was initially opened. + /// We store a symbol table parse time duration here because we might have + /// an object file and a symbol file which both have symbol tables. The parse + /// time for the symbol tables can be aggregated here. + StatsDuration m_symtab_parse_time; + /// We store a symbol named index time duration here because we might have + /// an object file and a symbol file which both have symbol tables. The parse + /// time for the symbol tables can be aggregated here. + StatsDuration m_symtab_index_time; + + std::once_flag m_optimization_warning; + std::once_flag m_language_warning; /// Resolve a file or load virtual address. /// @@ -1047,6 +1168,13 @@ private: Module(const Module &) = delete; const Module &operator=(const Module &) = delete; + + void LogMessage(Log *log, const llvm::formatv_object_base &payload); + void LogMessageVerboseBacktrace(Log *log, + const llvm::formatv_object_base &payload); + void ReportWarning(const llvm::formatv_object_base &payload); + void ReportError(const llvm::formatv_object_base &payload); + void ReportErrorIfModifyDetected(const llvm::formatv_object_base &payload); }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Core/ModuleList.h b/gnu/llvm/lldb/include/lldb/Core/ModuleList.h index 07dddd18357..631d7889f36 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ModuleList.h +++ b/gnu/llvm/lldb/include/lldb/Core/ModuleList.h @@ -45,6 +45,7 @@ class Target; class TypeList; class UUID; class VariableList; +struct ModuleFunctionSearchOptions; class ModuleListProperties : public Properties { mutable llvm::sys::RWMutex m_symlink_paths_mutex; @@ -59,6 +60,16 @@ public: bool SetClangModulesCachePath(const FileSpec &path); bool GetEnableExternalLookup() const; bool SetEnableExternalLookup(bool new_value); + bool GetEnableBackgroundLookup() const; + bool GetEnableLLDBIndexCache() const; + bool SetEnableLLDBIndexCache(bool new_value); + uint64_t GetLLDBIndexCacheMaxByteSize(); + uint64_t GetLLDBIndexCacheMaxPercent(); + uint64_t GetLLDBIndexCacheExpirationDays(); + FileSpec GetLLDBIndexCachePath() const; + bool SetLLDBIndexCachePath(const FileSpec &path); + + bool GetLoadSymbolOnDemand(); PathMappingList GetSymlinkMappings() const; }; @@ -158,7 +169,7 @@ public: /// ModulesDidLoad may be deferred when adding multiple Modules /// to the Target, but it must be called at the end, /// before resuming execution. - bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify = true); + bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify = true); void Append(const ModuleList &module_list); @@ -252,7 +263,7 @@ public: /// \see Module::FindFunctions () void FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, - bool include_symbols, bool include_inlines, + const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list) const; /// \see Module::FindFunctionSymbols () @@ -261,8 +272,9 @@ public: SymbolContextList &sc_list); /// \see Module::FindFunctions () - void FindFunctions(const RegularExpression &name, bool include_symbols, - bool include_inlines, SymbolContextList &sc_list); + void FindFunctions(const RegularExpression &name, + const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list); /// Find global and static variables by name. /// @@ -446,13 +458,28 @@ public: static void FindSharedModules(const ModuleSpec &module_spec, ModuleList &matching_module_list); + static lldb::ModuleSP FindSharedModule(const UUID &uuid); + static size_t RemoveOrphanSharedModules(bool mandatory); static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr); + /// Applies 'callback' to each module in this ModuleList. + /// If 'callback' returns false, iteration terminates. + /// The 'module_sp' passed to 'callback' is guaranteed to + /// be non-null. + /// + /// This function is thread-safe. void ForEach(std::function const &callback) const; + /// Returns true if 'callback' returns true for one of the modules + /// in this ModuleList. + /// + /// This function is thread-safe. + bool AnyOf( + std::function const &callback) const; + protected: // Class typedefs. typedef std::vector diff --git a/gnu/llvm/lldb/include/lldb/Core/ModuleSpec.h b/gnu/llvm/lldb/include/lldb/Core/ModuleSpec.h index 8e5deebbab9..451e347c9c7 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ModuleSpec.h +++ b/gnu/llvm/lldb/include/lldb/Core/ModuleSpec.h @@ -13,6 +13,7 @@ #include "lldb/Target/PathMappingList.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Iterable.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/UUID.h" @@ -25,18 +26,14 @@ namespace lldb_private { class ModuleSpec { public: - ModuleSpec() - : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(), - m_object_name(), m_source_mappings() {} + ModuleSpec() = default; /// If the \c data argument is passed, its contents will be used /// as the module contents instead of trying to read them from /// \c file_spec . ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(), lldb::DataBufferSP data = lldb::DataBufferSP()) - : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(), - m_uuid(uuid), m_object_name(), m_object_offset(0), m_source_mappings(), - m_data(data) { + : m_file(file_spec), m_uuid(uuid), m_object_offset(0), m_data(data) { if (data) m_object_size = data->GetByteSize(); else if (m_file) @@ -44,10 +41,8 @@ public: } ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch) - : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch), - m_uuid(), m_object_name(), m_object_offset(0), - m_object_size(FileSystem::Instance().GetByteSize(file_spec)), - m_source_mappings() {} + : m_file(file_spec), m_arch(arch), m_object_offset(0), + m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {} FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } @@ -279,9 +274,9 @@ protected: class ModuleSpecList { public: - ModuleSpecList() : m_specs(), m_mutex() {} + ModuleSpecList() = default; - ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() { + ModuleSpecList(const ModuleSpecList &rhs) { std::lock_guard lhs_guard(m_mutex); std::lock_guard rhs_guard(rhs.m_mutex); m_specs = rhs.m_specs; @@ -293,7 +288,7 @@ public: if (this != &rhs) { std::lock(m_mutex, rhs.m_mutex); std::lock_guard lhs_guard(m_mutex, std::adopt_lock); - std::lock_guard rhs_guard(rhs.m_mutex, + std::lock_guard rhs_guard(rhs.m_mutex, std::adopt_lock); m_specs = rhs.m_specs; } @@ -393,8 +388,16 @@ public: } } + typedef std::vector collection; + typedef LockingAdaptedIterable + ModuleSpecIterable; + + ModuleSpecIterable ModuleSpecs() { + return ModuleSpecIterable(m_specs, m_mutex); + } + protected: - typedef std::vector collection; ///< The module collection type. collection m_specs; ///< The collection of modules. mutable std::recursive_mutex m_mutex; }; diff --git a/gnu/llvm/lldb/include/lldb/Core/PluginInterface.h b/gnu/llvm/lldb/include/lldb/Core/PluginInterface.h index 5bdb2f45b66..e9fd2b263a9 100644 --- a/gnu/llvm/lldb/include/lldb/Core/PluginInterface.h +++ b/gnu/llvm/lldb/include/lldb/Core/PluginInterface.h @@ -9,7 +9,7 @@ #ifndef LLDB_CORE_PLUGININTERFACE_H #define LLDB_CORE_PLUGININTERFACE_H -#include "lldb/lldb-private.h" +#include "llvm/ADT/StringRef.h" namespace lldb_private { @@ -18,9 +18,7 @@ public: PluginInterface() = default; virtual ~PluginInterface() = default; - virtual ConstString GetPluginName() = 0; - - virtual uint32_t GetPluginVersion() = 0; + virtual llvm::StringRef GetPluginName() = 0; PluginInterface(const PluginInterface &) = delete; PluginInterface &operator=(const PluginInterface &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Core/PluginManager.h b/gnu/llvm/lldb/include/lldb/Core/PluginManager.h index be91929c62e..4e036e0d4ca 100644 --- a/gnu/llvm/lldb/include/lldb/Core/PluginManager.h +++ b/gnu/llvm/lldb/include/lldb/Core/PluginManager.h @@ -54,7 +54,7 @@ public: static void Terminate(); // ABI - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback); static bool UnregisterPlugin(ABICreateInstance create_callback); @@ -62,7 +62,7 @@ public: static ABICreateInstance GetABICreateCallbackAtIndex(uint32_t idx); // Architecture - static void RegisterPlugin(ConstString name, llvm::StringRef description, + static void RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ArchitectureCreateInstance create_callback); static void UnregisterPlugin(ArchitectureCreateInstance create_callback); @@ -71,7 +71,7 @@ public: CreateArchitectureInstance(const ArchSpec &arch); // Disassembler - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, DisassemblerCreateInstance create_callback); static bool UnregisterPlugin(DisassemblerCreateInstance create_callback); @@ -80,11 +80,11 @@ public: GetDisassemblerCreateCallbackAtIndex(uint32_t idx); static DisassemblerCreateInstance - GetDisassemblerCreateCallbackForPluginName(ConstString name); + GetDisassemblerCreateCallbackForPluginName(llvm::StringRef name); // DynamicLoader static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, DynamicLoaderCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr); @@ -94,11 +94,11 @@ public: GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx); static DynamicLoaderCreateInstance - GetDynamicLoaderCreateCallbackForPluginName(ConstString name); + GetDynamicLoaderCreateCallbackForPluginName(llvm::StringRef name); // JITLoader static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, JITLoaderCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr); @@ -108,7 +108,7 @@ public: GetJITLoaderCreateCallbackAtIndex(uint32_t idx); // EmulateInstruction - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, EmulateInstructionCreateInstance create_callback); static bool @@ -118,10 +118,10 @@ public: GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx); static EmulateInstructionCreateInstance - GetEmulateInstructionCreateCallbackForPluginName(ConstString name); + GetEmulateInstructionCreateCallbackForPluginName(llvm::StringRef name); // OperatingSystem - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, OperatingSystemCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback); @@ -131,10 +131,10 @@ public: GetOperatingSystemCreateCallbackAtIndex(uint32_t idx); static OperatingSystemCreateInstance - GetOperatingSystemCreateCallbackForPluginName(ConstString name); + GetOperatingSystemCreateCallbackForPluginName(llvm::StringRef name); // Language - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, LanguageCreateInstance create_callback); static bool UnregisterPlugin(LanguageCreateInstance create_callback); @@ -143,7 +143,7 @@ public: // LanguageRuntime static bool RegisterPlugin( - ConstString name, const char *description, + llvm::StringRef name, llvm::StringRef description, LanguageRuntimeCreateInstance create_callback, LanguageRuntimeGetCommandObject command_callback = nullptr, LanguageRuntimeGetExceptionPrecondition precondition_callback = nullptr); @@ -160,7 +160,7 @@ public: GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx); // SystemRuntime - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, SystemRuntimeCreateInstance create_callback); static bool UnregisterPlugin(SystemRuntimeCreateInstance create_callback); @@ -170,11 +170,12 @@ public: // ObjectFile static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ObjectFileCreateInstance create_callback, ObjectFileCreateMemoryInstance create_memory_callback, ObjectFileGetModuleSpecifications get_module_specifications, - ObjectFileSaveCore save_core = nullptr); + ObjectFileSaveCore save_core = nullptr, + DebuggerInitializeCallback debugger_init_callback = nullptr); static bool UnregisterPlugin(ObjectFileCreateInstance create_callback); @@ -188,29 +189,34 @@ public: GetObjectFileGetModuleSpecificationsCallbackAtIndex(uint32_t idx); static ObjectFileCreateMemoryInstance - GetObjectFileCreateMemoryCallbackForPluginName(ConstString name); + GetObjectFileCreateMemoryCallbackForPluginName(llvm::StringRef name); static Status SaveCore(const lldb::ProcessSP &process_sp, const FileSpec &outfile, - lldb::SaveCoreStyle &core_style); + lldb::SaveCoreStyle &core_style, + llvm::StringRef plugin_name); // ObjectContainer - static bool - RegisterPlugin(ConstString name, const char *description, - ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications); + static bool RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectContainerCreateMemoryInstance create_memory_callback = nullptr); static bool UnregisterPlugin(ObjectContainerCreateInstance create_callback); static ObjectContainerCreateInstance GetObjectContainerCreateCallbackAtIndex(uint32_t idx); + static ObjectContainerCreateMemoryInstance + GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx); + static ObjectFileGetModuleSpecifications GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx); // Platform static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, PlatformCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr); @@ -219,17 +225,17 @@ public: static PlatformCreateInstance GetPlatformCreateCallbackAtIndex(uint32_t idx); static PlatformCreateInstance - GetPlatformCreateCallbackForPluginName(ConstString name); + GetPlatformCreateCallbackForPluginName(llvm::StringRef name); - static const char *GetPlatformPluginNameAtIndex(uint32_t idx); + static llvm::StringRef GetPlatformPluginNameAtIndex(uint32_t idx); - static const char *GetPlatformPluginDescriptionAtIndex(uint32_t idx); + static llvm::StringRef GetPlatformPluginDescriptionAtIndex(uint32_t idx); static void AutoCompletePlatformName(llvm::StringRef partial_name, CompletionRequest &request); // Process static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ProcessCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr); @@ -238,17 +244,17 @@ public: static ProcessCreateInstance GetProcessCreateCallbackAtIndex(uint32_t idx); static ProcessCreateInstance - GetProcessCreateCallbackForPluginName(ConstString name); + GetProcessCreateCallbackForPluginName(llvm::StringRef name); - static const char *GetProcessPluginNameAtIndex(uint32_t idx); + static llvm::StringRef GetProcessPluginNameAtIndex(uint32_t idx); - static const char *GetProcessPluginDescriptionAtIndex(uint32_t idx); + static llvm::StringRef GetProcessPluginDescriptionAtIndex(uint32_t idx); static void AutoCompleteProcessName(llvm::StringRef partial_name, CompletionRequest &request); // ScriptInterpreter - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, lldb::ScriptLanguage script_lang, ScriptInterpreterCreateInstance create_callback); @@ -296,7 +302,7 @@ public: /// \return /// Returns true upon success; otherwise, false. static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, StructuredDataPluginCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr, StructuredDataFilterLaunchInfo filter_callback = nullptr); @@ -313,7 +319,7 @@ public: // SymbolFile static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, SymbolFileCreateInstance create_callback, DebuggerInitializeCallback debugger_init_callback = nullptr); @@ -323,7 +329,7 @@ public: GetSymbolFileCreateCallbackAtIndex(uint32_t idx); // SymbolVendor - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, SymbolVendorCreateInstance create_callback); static bool UnregisterPlugin(SymbolVendorCreateInstance create_callback); @@ -333,22 +339,23 @@ public: // Trace static bool RegisterPlugin( - ConstString name, const char *description, - TraceCreateInstanceForSessionFile create_callback_for_session_file, + llvm::StringRef name, llvm::StringRef description, + TraceCreateInstanceFromBundle create_callback_from_bundle, TraceCreateInstanceForLiveProcess create_callback_for_live_process, - llvm::StringRef schema); + llvm::StringRef schema, + DebuggerInitializeCallback debugger_init_callback); static bool - UnregisterPlugin(TraceCreateInstanceForSessionFile create_callback); + UnregisterPlugin(TraceCreateInstanceFromBundle create_callback); - static TraceCreateInstanceForSessionFile - GetTraceCreateCallback(ConstString plugin_name); + static TraceCreateInstanceFromBundle + GetTraceCreateCallback(llvm::StringRef plugin_name); static TraceCreateInstanceForLiveProcess - GetTraceCreateCallbackForLiveProcess(ConstString plugin_name); + GetTraceCreateCallbackForLiveProcess(llvm::StringRef plugin_name); - /// Get the JSON schema for a trace session file corresponding to the given - /// plugin. + /// Get the JSON schema for a trace bundle description file corresponding to + /// the given plugin. /// /// \param[in] plugin_name /// The name of the plugin. @@ -356,10 +363,10 @@ public: /// \return /// An empty \a StringRef if no plugin was found with that plugin name, /// otherwise the actual schema is returned. - static llvm::StringRef GetTraceSchema(ConstString plugin_name); + static llvm::StringRef GetTraceSchema(llvm::StringRef plugin_name); - /// Get the JSON schema for a trace session file corresponding to the plugin - /// given by its index. + /// Get the JSON schema for a trace bundle description file corresponding to + /// the plugin given by its index. /// /// \param[in] index /// The index of the plugin to get the schema of. @@ -375,16 +382,16 @@ public: /// This callback is used to create a CommandObject that will be listed /// under "thread trace export". Can be \b null. static bool RegisterPlugin( - ConstString name, const char *description, + llvm::StringRef name, llvm::StringRef description, TraceExporterCreateInstance create_callback, ThreadTraceExportCommandCreator create_thread_trace_export_command); static TraceExporterCreateInstance - GetTraceExporterCreateCallback(ConstString plugin_name); + GetTraceExporterCreateCallback(llvm::StringRef plugin_name); static bool UnregisterPlugin(TraceExporterCreateInstance create_callback); - static const char *GetTraceExporterPluginNameAtIndex(uint32_t index); + static llvm::StringRef GetTraceExporterPluginNameAtIndex(uint32_t index); /// Return the callback used to create the CommandObject that will be listed /// under "thread trace export". Can be \b null. @@ -392,7 +399,7 @@ public: GetThreadTraceExportCommandCreatorAtIndex(uint32_t index); // UnwindAssembly - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, UnwindAssemblyCreateInstance create_callback); static bool UnregisterPlugin(UnwindAssemblyCreateInstance create_callback); @@ -401,7 +408,7 @@ public: GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx); // MemoryHistory - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, MemoryHistoryCreateInstance create_callback); static bool UnregisterPlugin(MemoryHistoryCreateInstance create_callback); @@ -411,7 +418,7 @@ public: // InstrumentationRuntime static bool - RegisterPlugin(ConstString name, const char *description, + RegisterPlugin(llvm::StringRef name, llvm::StringRef description, InstrumentationRuntimeCreateInstance create_callback, InstrumentationRuntimeGetType get_type_callback); @@ -425,7 +432,7 @@ public: GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx); // TypeSystem - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, TypeSystemCreateInstance create_callback, LanguageSet supported_languages_for_types, LanguageSet supported_languages_for_expressions); @@ -440,7 +447,7 @@ public: static LanguageSet GetAllTypeSystemSupportedLanguagesForExpressions(); // REPL - static bool RegisterPlugin(ConstString name, const char *description, + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, REPLCreateInstance create_callback, LanguageSet supported_languages); @@ -448,6 +455,8 @@ public: static REPLCreateInstance GetREPLCreateCallbackAtIndex(uint32_t idx); + static LanguageSet GetREPLSupportedLanguagesAtIndex(uint32_t idx); + static LanguageSet GetREPLAllTypeSystemSupportedLanguages(); // Some plug-ins might register a DebuggerInitializeCallback callback when @@ -479,6 +488,17 @@ public: Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, ConstString description, bool is_global_property); + static bool CreateSettingForTracePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForObjectFilePlugin(Debugger &debugger, ConstString setting_name); + + static bool CreateSettingForObjectFilePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + static lldb::OptionValuePropertiesSP GetSettingForSymbolFilePlugin(Debugger &debugger, ConstString setting_name); diff --git a/gnu/llvm/lldb/include/lldb/Core/Progress.h b/gnu/llvm/lldb/include/lldb/Core/Progress.h index f625d014f26..48078705ae6 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Progress.h +++ b/gnu/llvm/lldb/include/lldb/Core/Progress.h @@ -13,6 +13,7 @@ #include "lldb/lldb-types.h" #include #include +#include namespace lldb_private { @@ -102,7 +103,7 @@ private: const uint64_t m_total; /// The optional debugger ID to report progress to. If this has no value then /// all debuggers will receive this event. - llvm::Optional m_debugger_id; + std::optional m_debugger_id; /// Set to true when progress has been reported where m_completed == m_total /// to ensure that we don't send progress updates after progress has /// completed. diff --git a/gnu/llvm/lldb/include/lldb/Core/RichManglingContext.h b/gnu/llvm/lldb/include/lldb/Core/RichManglingContext.h index 48102ec0b1c..3b79924e88a 100644 --- a/gnu/llvm/lldb/include/lldb/Core/RichManglingContext.h +++ b/gnu/llvm/lldb/include/lldb/Core/RichManglingContext.h @@ -42,29 +42,16 @@ public: /// If this symbol describes a constructor or destructor. bool IsCtorOrDtor() const; - /// If this symbol describes a function. - bool IsFunction() const; - /// Get the base name of a function. This doesn't include trailing template - /// arguments, ie "a::b" gives "b". The result will overwrite the - /// internal buffer. It can be obtained via GetBufferRef(). - void ParseFunctionBaseName(); + /// arguments, ie "a::b" gives "b". + llvm::StringRef ParseFunctionBaseName(); /// Get the context name for a function. For "a::b::c", this function returns - /// "a::b". The result will overwrite the internal buffer. It can be obtained - /// via GetBufferRef(). - void ParseFunctionDeclContextName(); - - /// Get the entire demangled name. The result will overwrite the internal - /// buffer. It can be obtained via GetBufferRef(). - void ParseFullName(); - - /// Obtain a StringRef to the internal buffer that holds the result of the - /// most recent ParseXy() operation. The next ParseXy() call invalidates it. - llvm::StringRef GetBufferRef() const { - assert(m_provider != None && "Initialize a provider first"); - return m_buffer; - } + /// "a::b". + llvm::StringRef ParseFunctionDeclContextName(); + + /// Get the entire demangled name. + llvm::StringRef ParseFullName(); private: enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage }; @@ -72,9 +59,6 @@ private: /// Selects the rich mangling info provider. InfoProvider m_provider = None; - /// Reference to the buffer used for results of ParseXy() operations. - llvm::StringRef m_buffer; - /// Members for ItaniumPartialDemangler llvm::ItaniumPartialDemangler m_ipd; /// Note: m_ipd_buf is a raw pointer due to being resized by realloc via @@ -96,15 +80,15 @@ private: void ResetProvider(InfoProvider new_provider); /// Uniform handling of string buffers for ItaniumPartialDemangler. - void processIPDStrResult(char *ipd_res, size_t res_len); + llvm::StringRef processIPDStrResult(char *ipd_res, size_t res_len); /// Cast the given parser to the given type. Ideally we would have a type /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we /// can't access CPlusPlusLanguage::MethodName from within the header. template static ParserT *get(llvm::Any parser) { - assert(parser.hasValue()); - assert(llvm::any_isa(parser)); - return llvm::any_cast(parser); + assert(parser.has_value()); + assert(llvm::any_cast(&parser)); + return *llvm::any_cast(&parser); } }; diff --git a/gnu/llvm/lldb/include/lldb/Core/Section.h b/gnu/llvm/lldb/include/lldb/Core/Section.h index 3d4ab154e74..8a9fea37431 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Section.h +++ b/gnu/llvm/lldb/include/lldb/Core/Section.h @@ -89,6 +89,12 @@ public: void Clear() { m_sections.clear(); } + /// Get the debug information size from all sections that contain debug + /// information. Symbol tables are not considered part of the debug + /// information for this call, just known sections that contain debug + /// information. + uint64_t GetDebugInfoSize() const; + protected: collection m_sections; }; @@ -236,6 +242,13 @@ public: void SetIsRelocated(bool b) { m_relocated = b; } + /// Returns true if this section contains debug information. Symbol tables + /// are not considered debug information since some symbols might contain + /// debug information (STABS, COFF) but not all symbols do, so to keep this + /// fast and simple only sections that contains only debug information should + /// return true. + bool ContainsOnlyDebugInfo() const; + protected: ObjectFile *m_obj_file; // The object file that data for this section should // be read from diff --git a/gnu/llvm/lldb/include/lldb/Core/SourceLocationSpec.h b/gnu/llvm/lldb/include/lldb/Core/SourceLocationSpec.h index 808931186db..9c2512bff4b 100644 --- a/gnu/llvm/lldb/include/lldb/Core/SourceLocationSpec.h +++ b/gnu/llvm/lldb/include/lldb/Core/SourceLocationSpec.h @@ -11,8 +11,8 @@ #include "lldb/Core/Declaration.h" #include "lldb/lldb-defines.h" -#include "llvm/ADT/Optional.h" +#include #include namespace lldb_private { @@ -29,7 +29,7 @@ public: /// Constructor. /// /// Takes a \a file_spec with a \a line number and a \a column number. If - /// \a column is null or not provided, it is set to llvm::None. + /// \a column is null or not provided, it is set to std::nullopt. /// /// \param[in] file_spec /// The full or partial path to a file. @@ -47,7 +47,7 @@ public: /// Whether to look for an exact match. /// explicit SourceLocationSpec(FileSpec file_spec, uint32_t line, - llvm::Optional column = llvm::None, + std::optional column = std::nullopt, bool check_inlines = false, bool exact_match = false); @@ -165,9 +165,9 @@ public: FileSpec GetFileSpec() const { return m_declaration.GetFile(); } - llvm::Optional GetLine() const; + std::optional GetLine() const; - llvm::Optional GetColumn() const; + std::optional GetColumn() const; bool GetCheckInlines() const { return m_check_inlines; } diff --git a/gnu/llvm/lldb/include/lldb/Core/SourceManager.h b/gnu/llvm/lldb/include/lldb/Core/SourceManager.h index 5f2c1de8465..c272f7f4311 100644 --- a/gnu/llvm/lldb/include/lldb/Core/SourceManager.h +++ b/gnu/llvm/lldb/include/lldb/Core/SourceManager.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ public: void UpdateIfNeeded(); - size_t DisplaySourceLines(uint32_t line, llvm::Optional column, + size_t DisplaySourceLines(uint32_t line, std::optional column, uint32_t context_before, uint32_t context_after, Stream *s); void FindLinesMatchingRegex(RegularExpression ®ex, uint32_t start_line, diff --git a/gnu/llvm/lldb/include/lldb/Core/StreamAsynchronousIO.h b/gnu/llvm/lldb/include/lldb/Core/StreamAsynchronousIO.h index 30eff55b2e5..b7adbc42096 100644 --- a/gnu/llvm/lldb/include/lldb/Core/StreamAsynchronousIO.h +++ b/gnu/llvm/lldb/include/lldb/Core/StreamAsynchronousIO.h @@ -20,7 +20,7 @@ class Debugger; class StreamAsynchronousIO : public Stream { public: - StreamAsynchronousIO(Debugger &debugger, bool for_stdout); + StreamAsynchronousIO(Debugger &debugger, bool for_stdout, bool colors); ~StreamAsynchronousIO() override; diff --git a/gnu/llvm/lldb/include/lldb/Core/StructuredDataImpl.h b/gnu/llvm/lldb/include/lldb/Core/StructuredDataImpl.h index 929ce21fb2f..16dbc5263b2 100644 --- a/gnu/llvm/lldb/include/lldb/Core/StructuredDataImpl.h +++ b/gnu/llvm/lldb/include/lldb/Core/StructuredDataImpl.h @@ -25,10 +25,13 @@ namespace lldb_private { class StructuredDataImpl { public: - StructuredDataImpl() : m_plugin_wp(), m_data_sp() {} + StructuredDataImpl() = default; StructuredDataImpl(const StructuredDataImpl &rhs) = default; + StructuredDataImpl(StructuredData::ObjectSP obj) + : m_data_sp(std::move(obj)) {} + StructuredDataImpl(const lldb::EventSP &event_sp) : m_plugin_wp( EventDataStructuredData::GetPluginFromEvent(event_sp.get())), @@ -77,7 +80,7 @@ public: error.SetErrorString("No data to describe."); return error; } - m_data_sp->Dump(stream, true); + m_data_sp->GetDescription(stream); return error; } // Get the data's description. @@ -152,6 +155,8 @@ public: return (::snprintf(dst, dst_len, "%s", result.data())); } + StructuredData::ObjectSP GetObjectSP() const { return m_data_sp; } + private: lldb::StructuredDataPluginWP m_plugin_wp; StructuredData::ObjectSP m_data_sp; diff --git a/gnu/llvm/lldb/include/lldb/Core/ThreadSafeValue.h b/gnu/llvm/lldb/include/lldb/Core/ThreadSafeValue.h index 51820ec9cd9..ddd7b56e82c 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ThreadSafeValue.h +++ b/gnu/llvm/lldb/include/lldb/Core/ThreadSafeValue.h @@ -18,7 +18,7 @@ namespace lldb_private { template class ThreadSafeValue { public: ThreadSafeValue() = default; - ThreadSafeValue(const T &value) : m_value(value), m_mutex() {} + ThreadSafeValue(const T &value) : m_value(value) {} ~ThreadSafeValue() = default; @@ -42,6 +42,7 @@ public: // Call this if you have already manually locked the mutex using the // GetMutex() accessor + // coverity[missing_lock] void SetValueNoLock(const T &value) { m_value = value; } std::recursive_mutex &GetMutex() { return m_mutex; } diff --git a/gnu/llvm/lldb/include/lldb/Core/ThreadedCommunication.h b/gnu/llvm/lldb/include/lldb/Core/ThreadedCommunication.h new file mode 100644 index 00000000000..2e3afde3c05 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Core/ThreadedCommunication.h @@ -0,0 +1,288 @@ +//===-- ThreadedCommunication.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_CORE_THREADEDCOMMUNICATION_H +#define LLDB_CORE_THREADEDCOMMUNICATION_H + +#include "lldb/Core/Communication.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" + +#include +#include +#include + +#include +#include + +namespace lldb_private { + +/// \class ThreadedCommunication ThreadedCommunication.h +/// "lldb/Core/ThreadedCommunication.h" Variation of Communication that +/// supports threaded reads. +/// +/// ThreadedCommunication enhances the base Communication class with support +/// for multi-threaded mode. In this mode, a read thread is spawned that +/// continually reads data and caches any received bytes. To start the read +/// thread clients call: +/// +/// bool ThreadedCommunication::StartReadThread (Status *); +/// +/// If true is returned a read thread has been spawned that will continually +/// execute a call to the pure virtual DoRead function: +/// +/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); +/// +/// When bytes are received the data gets cached in \a m_bytes and this class +/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that +/// want packet based communication should override AppendBytesToCache. The +/// subclasses can choose to call the built in AppendBytesToCache with the \a +/// broadcast parameter set to false. This will cause the \b +/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the +/// subclass can post a \b eBroadcastBitPacketAvailable event when a full +/// packet of data has been received. +/// +/// If the connection is disconnected a \b eBroadcastBitDisconnected event +/// gets broadcast. If the read thread exits a \b +/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also +/// post a \b eBroadcastBitReadThreadShouldExit event to this object which +/// will cause the read thread to exit. +/// +/// ThreadedCommunication inherits from Broadcaster which means it can be used +/// in conjunction with Listener to wait for multiple broadcaster objects and +/// multiple events from each of those objects. ThreadedCommunication defines a +/// set of pre-defined event bits (see enumerations definitions that start with +/// "eBroadcastBit" below). +class ThreadedCommunication : public Communication, public Broadcaster { + using Communication::Communication; + +public: + FLAGS_ANONYMOUS_ENUM(){ + eBroadcastBitDisconnected = + (1u << 0), ///< Sent when the communications connection is lost. + eBroadcastBitReadThreadGotBytes = + (1u << 1), ///< Sent by the read thread when bytes become available. + eBroadcastBitReadThreadDidExit = + (1u + << 2), ///< Sent by the read thread when it exits to inform clients. + eBroadcastBitReadThreadShouldExit = + (1u << 3), ///< Sent by clients that need to cancel the read thread. + eBroadcastBitPacketAvailable = + (1u << 4), ///< Sent when data received makes a complete packet. + eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread + /// to indicate all pending + /// input has been processed. + }; + + typedef void (*ReadThreadBytesReceived)(void *baton, const void *src, + size_t src_len); + + /// Construct the ThreadedCommunication object with the specified name for the + /// Broadcaster that this object inherits from. + /// + /// \param[in] broadcaster_name + /// The name of the broadcaster object. This name should be as + /// complete as possible to uniquely identify this object. The + /// broadcaster name can be updated after the connect function + /// is called. + ThreadedCommunication(const char *broadcaster_name); + + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + ~ThreadedCommunication() override; + + void Clear() override; + + /// Disconnect the communications connection if one is currently connected. + /// + /// \return + /// \b True if the disconnect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// \see Status& Communication::GetError (); + /// \see bool Connection::Disconnect (); + lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr) override; + + /// Read bytes from the current connection. + /// + /// If no read thread is running, this function call the connection's + /// Connection::Read(...) function to get any available. + /// + /// If a read thread has been started, this function will check for any + /// cached bytes that have already been read and return any currently + /// available bytes. If no bytes are cached, it will wait for the bytes to + /// become available by listening for the \a eBroadcastBitReadThreadGotBytes + /// event. If this function consumes all of the bytes in the cache, it will + /// reset the \a eBroadcastBitReadThreadGotBytes event bit. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read, and also the max + /// number of bytes that can be placed into \a dst. + /// + /// \param[in] timeout + /// A timeout value or std::nullopt for no timeout. + /// + /// \return + /// The number of bytes actually read. + /// + /// \see size_t Connection::Read (void *, size_t); + size_t Read(void *dst, size_t dst_len, const Timeout &timeout, + lldb::ConnectionStatus &status, Status *error_ptr) override; + + /// Sets the connection that it to be used by this class. + /// + /// By making a communication class that uses different connections it + /// allows a single communication interface to negotiate and change its + /// connection without any interruption to the client. It also allows the + /// Communication class to be subclassed for packet based communication. + /// + /// \param[in] connection + /// A connection that this class will own and destroy. + /// + /// \see + /// class Connection + void SetConnection(std::unique_ptr connection) override; + + /// Starts a read thread whose sole purpose it to read bytes from the + /// current connection. This function will call connection's read function: + /// + /// size_t Connection::Read (void *, size_t); + /// + /// When bytes are read and cached, this function will call: + /// + /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, + /// bool + /// broadcast); + /// + /// Subclasses should override this function if they wish to override the + /// default action of caching the bytes and broadcasting a \b + /// eBroadcastBitReadThreadGotBytes event. + /// + /// \return + /// \b True if the read thread was successfully started, \b + /// false otherwise. + /// + /// \see size_t Connection::Read (void *, size_t); + /// \see void Communication::AppendBytesToCache (const uint8_t * bytes, + /// size_t len, bool broadcast); + virtual bool StartReadThread(Status *error_ptr = nullptr); + + /// Stops the read thread by cancelling it. + /// + /// \return + /// \b True if the read thread was successfully canceled, \b + /// false otherwise. + virtual bool StopReadThread(Status *error_ptr = nullptr); + + virtual bool JoinReadThread(Status *error_ptr = nullptr); + /// Checks if there is a currently running read thread. + /// + /// \return + /// \b True if the read thread is running, \b false otherwise. + bool ReadThreadIsRunning(); + + /// The read thread function. This function will call the "DoRead" + /// function continuously and wait for data to become available. When data + /// is received it will append the available data to the internal cache and + /// broadcast a \b eBroadcastBitReadThreadGotBytes event. + /// + /// \param[in] comm_ptr + /// A pointer to an instance of this class. + /// + /// \return + /// \b NULL. + /// + /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); + lldb::thread_result_t ReadThread(); + + void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, + void *callback_baton); + + /// Wait for the read thread to process all outstanding data. + /// + /// After this function returns, the read thread has processed all data that + /// has been waiting in the Connection queue. + /// + void SynchronizeWithReadThread(); + + static ConstString &GetStaticBroadcasterClass(); + + ConstString &GetBroadcasterClass() const override { + return GetStaticBroadcasterClass(); + } + +protected: + HostThread m_read_thread; ///< The read thread handle in case we need to + /// cancel the thread. + std::atomic m_read_thread_enabled; + std::atomic m_read_thread_did_exit; + std::string + m_bytes; ///< A buffer to cache bytes read in the ReadThread function. + std::recursive_mutex m_bytes_mutex; ///< A mutex to protect multi-threaded + /// access to the cached bytes. + lldb::ConnectionStatus m_pass_status; ///< Connection status passthrough + /// from read thread. + Status m_pass_error; ///< Error passthrough from read thread. + std::mutex m_synchronize_mutex; + ReadThreadBytesReceived m_callback; + void *m_callback_baton; + + /// Append new bytes that get read from the read thread into the internal + /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes + /// event to be broadcast if \a broadcast is true. + /// + /// Subclasses can override this function in order to inspect the received + /// data and check if a packet is available. + /// + /// Subclasses can also still call this function from the overridden method + /// to allow the caching to correctly happen and suppress the broadcasting + /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast + /// to false. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to append to the cache. + virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, + bool broadcast, + lldb::ConnectionStatus status); + + /// Get any available bytes from our data cache. If this call empties the + /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset + /// to signify no more bytes are available. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read from the cache, + /// and also the max number of bytes that can be placed into + /// \a dst. + /// + /// \return + /// The number of bytes extracted from the data cache. + size_t GetCachedBytes(void *dst, size_t dst_len); + +private: + ThreadedCommunication(const ThreadedCommunication &) = delete; + const ThreadedCommunication & + operator=(const ThreadedCommunication &) = delete; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_THREADEDCOMMUNICATION_H diff --git a/gnu/llvm/lldb/include/lldb/Core/UniqueCStringMap.h b/gnu/llvm/lldb/include/lldb/Core/UniqueCStringMap.h index e37027a0150..9c8b8081d37 100644 --- a/gnu/llvm/lldb/include/lldb/Core/UniqueCStringMap.h +++ b/gnu/llvm/lldb/include/lldb/Core/UniqueCStringMap.h @@ -165,7 +165,21 @@ public: // my_map.Append (UniqueCStringMap::Entry(GetName(...), GetValue(...))); // } // my_map.Sort(); - void Sort() { llvm::sort(m_map.begin(), m_map.end(), Compare()); } + void Sort() { + Sort([](const T &, const T &) { return false; }); + } + + /// Sort contents of this map using the provided comparator to break ties for + /// entries with the same string value. + template void Sort(TCompare tc) { + Compare c; + llvm::sort(m_map, [&](const Entry &lhs, const Entry &rhs) -> bool { + int result = c.ThreeWay(lhs.cstring, rhs.cstring); + if (result == 0) + return tc(lhs.value, rhs.value); + return result < 0; + }); + } // Since we are using a vector to contain our items it will always double its // memory consumption as things are added to the vector, so if you intend to @@ -205,13 +219,24 @@ protected: return operator()(lhs, rhs.cstring); } + bool operator()(ConstString lhs, ConstString rhs) { + return ThreeWay(lhs, rhs) < 0; + } + // This is only for uniqueness, not lexicographical ordering, so we can // just compare pointers. *However*, comparing pointers from different // allocations is UB, so we need compare their integral values instead. - bool operator()(ConstString lhs, ConstString rhs) { - return uintptr_t(lhs.GetCString()) < uintptr_t(rhs.GetCString()); + int ThreeWay(ConstString lhs, ConstString rhs) { + auto lhsint = uintptr_t(lhs.GetCString()); + auto rhsint = uintptr_t(rhs.GetCString()); + if (lhsint < rhsint) + return -1; + if (lhsint > rhsint) + return 1; + return 0; } }; + collection m_map; }; diff --git a/gnu/llvm/lldb/include/lldb/Core/UserSettingsController.h b/gnu/llvm/lldb/include/lldb/Core/UserSettingsController.h index 35555f08c35..8afef063597 100644 --- a/gnu/llvm/lldb/include/lldb/Core/UserSettingsController.h +++ b/gnu/llvm/lldb/include/lldb/Core/UserSettingsController.h @@ -57,10 +57,11 @@ public: virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask); + uint32_t dump_mask, bool is_json = false); virtual void DumpAllPropertyValues(const ExecutionContext *exe_ctx, - Stream &strm, uint32_t dump_mask); + Stream &strm, uint32_t dump_mask, + bool is_json = false); virtual void DumpAllDescriptions(CommandInterpreter &interpreter, Stream &strm) const; diff --git a/gnu/llvm/lldb/include/lldb/Core/Value.h b/gnu/llvm/lldb/include/lldb/Core/Value.h index 1ee4fe639e6..fdda9f1db49 100644 --- a/gnu/llvm/lldb/include/lldb/Core/Value.h +++ b/gnu/llvm/lldb/include/lldb/Core/Value.h @@ -156,13 +156,11 @@ protected: class ValueList { public: - ValueList() : m_values() {} - - ValueList(const ValueList &rhs); - + ValueList() = default; ~ValueList() = default; - const ValueList &operator=(const ValueList &rhs); + ValueList(const ValueList &rhs) = default; + ValueList &operator=(const ValueList &rhs) = default; // void InsertValue (Value *value, size_t idx); void PushValue(const Value &value); diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObject.h b/gnu/llvm/lldb/include/lldb/Core/ValueObject.h index 5f1cbc65b32..a666d0bab17 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObject.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObject.h @@ -26,7 +26,6 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -34,6 +33,7 @@ #include #include #include +#include #include #include @@ -357,7 +357,7 @@ public: virtual bool CanProvideValue(); // Subclasses must implement the functions below. - virtual llvm::Optional GetByteSize() = 0; + virtual std::optional GetByteSize() = 0; virtual lldb::ValueType GetValueType() const = 0; @@ -679,7 +679,7 @@ public: bool IsCStringContainer(bool check_pointer = false); std::pair - ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error, + ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, Status &error, uint32_t max_length = 0, bool honor_array = true, lldb::Format item_format = lldb::eFormatCharArray); @@ -795,7 +795,7 @@ protected: class ChildrenManager { public: - ChildrenManager() : m_mutex(), m_children() {} + ChildrenManager() = default; bool HasChildAtIndex(size_t idx) { std::lock_guard guard(m_mutex); @@ -1000,7 +1000,7 @@ protected: void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType); protected: - virtual void DoUpdateChildrenAddressType(ValueObject &valobj) { return; }; + virtual void DoUpdateChildrenAddressType(ValueObject &valobj){}; private: virtual CompilerType MaybeCalculateCompleteType(); diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectCast.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectCast.h index 84cf13353ae..fe053c12d9c 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectCast.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectCast.h @@ -17,6 +17,7 @@ #include #include +#include namespace lldb_private { class ConstString; @@ -30,7 +31,7 @@ public: ConstString name, const CompilerType &cast_type); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; size_t CalculateNumChildren(uint32_t max) override; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectChild.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectChild.h index 8a7a7f17bc7..07b37aa8a40 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectChild.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectChild.h @@ -18,10 +18,9 @@ #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-types.h" -#include "llvm/ADT/Optional.h" - #include #include +#include namespace lldb_private { @@ -30,7 +29,7 @@ class ValueObjectChild : public ValueObject { public: ~ValueObjectChild() override; - llvm::Optional GetByteSize() override { return m_byte_size; } + std::optional GetByteSize() override { return m_byte_size; } lldb::offset_t GetByteOffset() override { return m_byte_offset; } @@ -69,7 +68,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; + std::optional m_can_update_with_invalid_exe_ctx; friend class ValueObject; friend class ValueObjectConstResult; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResult.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResult.h index 58cda6fd619..4edd4952160 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResult.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResult.h @@ -23,6 +23,7 @@ #include #include +#include namespace lldb_private { class DataExtractor; @@ -62,7 +63,7 @@ public: static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const Status &error); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; lldb::ValueType GetValueType() const override; @@ -113,7 +114,7 @@ protected: CompilerType GetCompilerTypeImpl() override; ConstString m_type_name; - llvm::Optional m_byte_size; + std::optional m_byte_size; ValueObjectConstResultImpl m_impl; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResultImpl.h index 2536c51fa57..5a7a079d309 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResultImpl.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectConstResultImpl.h @@ -68,7 +68,6 @@ private: ValueObject *m_impl_backend; lldb::addr_t m_live_address; AddressType m_live_address_type; - lldb::ValueObjectSP m_load_addr_backend; lldb::ValueObjectSP m_address_of_backend; ValueObjectConstResultImpl(const ValueObjectConstResultImpl &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectDynamicValue.h index 8822a1d3924..2758b4e5bb5 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectDynamicValue.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace lldb_private { class DataExtractor; @@ -32,9 +33,9 @@ class Status; /// set lldb type. class ValueObjectDynamicValue : public ValueObject { public: - ~ValueObjectDynamicValue() override; + ~ValueObjectDynamicValue() override = default; - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; ConstString GetTypeName() override; @@ -68,14 +69,6 @@ public: 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() == nullptr); - m_owning_valobj_sp = owning_sp; - } - bool SetValueFromCString(const char *value_str, Status &error) override; bool SetData(DataExtractor &data, Status &error) override; @@ -117,7 +110,6 @@ protected: 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 - lldb::ValueObjectSP m_owning_valobj_sp; lldb::DynamicValueType m_use_dynamic; TypeImpl m_type_impl; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectMemory.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectMemory.h index 83671a794b5..3c01df388d2 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectMemory.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectMemory.h @@ -20,6 +20,7 @@ #include #include +#include namespace lldb_private { class ExecutionContextScope; @@ -40,7 +41,7 @@ public: const Address &address, const CompilerType &ast_type); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; ConstString GetTypeName() override; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectRegister.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectRegister.h index e210b36d2a4..60c299c5fb4 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectRegister.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectRegister.h @@ -20,6 +20,7 @@ #include #include +#include namespace lldb_private { class DataExtractor; @@ -36,7 +37,7 @@ public: lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; lldb::ValueType GetValueType() const override { return lldb::eValueTypeRegisterSet; @@ -84,9 +85,9 @@ public: static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num); + const RegisterInfo *reg_info); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; lldb::ValueType GetValueType() const override { return lldb::eValueTypeRegister; @@ -119,15 +120,16 @@ protected: CompilerType m_compiler_type; private: - void ConstructObject(uint32_t reg_num); + void ConstructObject(const RegisterInfo *reg_info); friend class ValueObjectRegisterSet; ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num); + const RegisterInfo *reg_info); ValueObjectRegister(ExecutionContextScope *exe_scope, ValueObjectManager &manager, - lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + lldb::RegisterContextSP ®_ctx_sp, + const RegisterInfo *reg_info); // For ValueObject only ValueObjectRegister(const ValueObjectRegister &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h index f7a233047cc..bdd6c1be421 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -36,7 +37,7 @@ class ValueObjectSynthetic : public ValueObject { public: ~ValueObjectSynthetic() override; - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; ConstString GetTypeName() override; diff --git a/gnu/llvm/lldb/include/lldb/Core/ValueObjectVariable.h b/gnu/llvm/lldb/include/lldb/Core/ValueObjectVariable.h index cbf7e5b52ce..bba28ce567b 100644 --- a/gnu/llvm/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/gnu/llvm/lldb/include/lldb/Core/ValueObjectVariable.h @@ -20,6 +20,7 @@ #include #include +#include namespace lldb_private { class DataExtractor; @@ -37,7 +38,7 @@ public: static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); - llvm::Optional GetByteSize() override; + std::optional GetByteSize() override; ConstString GetTypeName() override; diff --git a/gnu/llvm/lldb/include/lldb/Core/dwarf.h b/gnu/llvm/lldb/include/lldb/Core/dwarf.h index 968418e71c2..60fbdec40be 100644 --- a/gnu/llvm/lldb/include/lldb/Core/dwarf.h +++ b/gnu/llvm/lldb/include/lldb/Core/dwarf.h @@ -15,8 +15,11 @@ // Get the DWARF constant definitions from llvm #include "llvm/BinaryFormat/Dwarf.h" -// and stuff them in our default namespace -using namespace llvm::dwarf; +namespace lldb_private { +namespace dwarf { + using namespace llvm::dwarf; +} +} typedef uint32_t dw_uleb128_t; typedef int32_t dw_sleb128_t; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/DataVisualization.h b/gnu/llvm/lldb/include/lldb/DataFormatters/DataVisualization.h index 7be07d65acd..5aea29132b8 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/DataVisualization.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/DataVisualization.h @@ -51,7 +51,7 @@ public: GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic); static bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h b/gnu/llvm/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h index cef43f45b8e..c6306c7dab6 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/DumpValueObjectOptions.h @@ -66,7 +66,7 @@ public: DumpValueObjectOptions & SetMaximumPointerDepth(PointerDepth depth = {PointerDepth::Mode::Never, 0}); - DumpValueObjectOptions &SetMaximumDepth(uint32_t depth = 0); + DumpValueObjectOptions &SetMaximumDepth(uint32_t depth, bool is_default); DumpValueObjectOptions &SetDeclPrintingHelper(DeclPrintingHelper helper); @@ -125,6 +125,7 @@ public: SetPointerAsArray(const PointerAsArraySettings &ptr_array); uint32_t m_max_depth = UINT32_MAX; + bool m_max_depth_is_default = true; lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; uint32_t m_omit_summary_depth = 0; lldb::Format m_format = lldb::eFormatDefault; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/FormatClasses.h b/gnu/llvm/lldb/include/lldb/DataFormatters/FormatClasses.h index b8540de3d74..a6bc3a35425 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/FormatClasses.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/FormatClasses.h @@ -17,6 +17,7 @@ #include "lldb/DataFormatters/TypeFormat.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" #include "lldb/lldb-enumerations.h" @@ -43,20 +44,57 @@ public: class FormattersMatchCandidate { public: - FormattersMatchCandidate(ConstString name, bool strip_ptr, - bool strip_ref, bool strip_tydef) - : m_type_name(name), m_stripped_pointer(strip_ptr), - m_stripped_reference(strip_ref), m_stripped_typedef(strip_tydef) {} + // Contains flags to indicate how this candidate was generated (e.g. if + // typedefs were stripped, or pointers were skipped). These are later compared + // to flags in formatters to confirm a string match. + struct Flags { + bool stripped_pointer = false; + bool stripped_reference = false; + bool stripped_typedef = false; + + // Returns a copy of this with the "stripped pointer" flag set. + Flags WithStrippedPointer() { + Flags result(*this); + result.stripped_pointer = true; + return result; + } + + // Returns a copy of this with the "stripped reference" flag set. + Flags WithStrippedReference() { + Flags result(*this); + result.stripped_reference = true; + return result; + } + + // Returns a copy of this with the "stripped typedef" flag set. + Flags WithStrippedTypedef() { + Flags result(*this); + result.stripped_typedef = true; + return result; + } + }; + + FormattersMatchCandidate(ConstString name, + ScriptInterpreter *script_interpreter, TypeImpl type, + Flags flags) + : m_type_name(name), m_script_interpreter(script_interpreter), + m_type(type), m_flags(flags) {} ~FormattersMatchCandidate() = default; ConstString GetTypeName() const { return m_type_name; } - bool DidStripPointer() const { return m_stripped_pointer; } + TypeImpl GetType() const { return m_type; } + + ScriptInterpreter *GetScriptInterpreter() const { + return m_script_interpreter; + } - bool DidStripReference() const { return m_stripped_reference; } + bool DidStripPointer() const { return m_flags.stripped_pointer; } - bool DidStripTypedef() const { return m_stripped_typedef; } + bool DidStripReference() const { return m_flags.stripped_reference; } + + bool DidStripTypedef() const { return m_flags.stripped_typedef; } template bool IsMatch(const std::shared_ptr &formatter_sp) const { @@ -73,9 +111,11 @@ public: private: ConstString m_type_name; - bool m_stripped_pointer; - bool m_stripped_reference; - bool m_stripped_typedef; + // If a formatter provides a matching callback function, we need the script + // interpreter and the type object (as an argument to the callback). + ScriptInterpreter *m_script_interpreter; + TypeImpl m_type; + Flags m_flags; }; typedef std::vector FormattersMatchVector; @@ -105,23 +145,25 @@ private: class TypeNameSpecifierImpl { public: - TypeNameSpecifierImpl() : m_type() {} + TypeNameSpecifierImpl() = default; - TypeNameSpecifierImpl(llvm::StringRef name, bool is_regex) - : m_is_regex(is_regex), m_type() { + TypeNameSpecifierImpl(llvm::StringRef name, + lldb::FormatterMatchType match_type) + : m_match_type(match_type) { m_type.m_type_name = std::string(name); } - // if constructing with a given type, is_regex cannot be true since we are - // giving an exact type to match - TypeNameSpecifierImpl(lldb::TypeSP type) : m_is_regex(false), m_type() { + // if constructing with a given type, we consider that a case of exact match. + TypeNameSpecifierImpl(lldb::TypeSP type) + : m_match_type(lldb::eFormatterMatchExact) { if (type) { m_type.m_type_name = std::string(type->GetName().GetStringRef()); m_type.m_compiler_type = type->GetForwardCompilerType(); } } - TypeNameSpecifierImpl(CompilerType type) : m_is_regex(false), m_type() { + TypeNameSpecifierImpl(CompilerType type) + : m_match_type(lldb::eFormatterMatchExact) { if (type.IsValid()) { m_type.m_type_name.assign(type.GetTypeName().GetCString()); m_type.m_compiler_type = type; @@ -140,10 +182,12 @@ public: return CompilerType(); } - bool IsRegex() { return m_is_regex; } + lldb::FormatterMatchType GetMatchType() { return m_match_type; } + + bool IsRegex() { return m_match_type == lldb::eFormatterMatchRegex; } private: - bool m_is_regex = false; + lldb::FormatterMatchType m_match_type = lldb::eFormatterMatchExact; // TODO: Replace this with TypeAndOrName. struct TypeOrName { std::string m_type_name; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/FormatManager.h b/gnu/llvm/lldb/include/lldb/DataFormatters/FormatManager.h index 978ad148d6c..295d3b84342 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/FormatManager.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/FormatManager.h @@ -128,12 +128,12 @@ public: GetSyntheticChildren(ValueObject &valobj, lldb::DynamicValueType use_dynamic); bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, 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, only_enabled, + return m_categories_map.AnyMatches(candidate_type, items, only_enabled, matching_category, matching_type); } @@ -162,8 +162,8 @@ public: static FormattersMatchVector GetPossibleMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic) { FormattersMatchVector matches; - GetPossibleMatches(valobj, valobj.GetCompilerType(), - use_dynamic, matches, false, false, false, true); + GetPossibleMatches(valobj, valobj.GetCompilerType(), use_dynamic, matches, + FormattersMatchCandidate::Flags(), true); return matches; } @@ -179,8 +179,7 @@ private: CompilerType compiler_type, lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, - bool did_strip_ptr, bool did_strip_ref, - bool did_strip_typedef, + FormattersMatchCandidate::Flags current_flags, bool root_level = false); std::atomic m_last_revision; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersContainer.h b/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersContainer.h index 2f56218c43a..fd046e773b6 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersContainer.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -39,11 +39,17 @@ public: /// Class for matching type names. class TypeMatcher { + /// Type name for exact match, or name of the python callback if m_match_type + /// is `eFormatterMatchCallback`. + ConstString m_name; RegularExpression m_type_name_regex; - ConstString m_type_name; - /// False if m_type_name_regex should be used for matching. False if this is - /// just matching by comparing with m_type_name string. - bool m_is_regex; + /// Indicates what kind of matching strategy should be used: + /// - eFormatterMatchExact: match the exact type name in m_name. + /// - eFormatterMatchRegex: match using the RegularExpression object + /// `m_type_name_regex` instead. + /// - eFormatterMatchCallback: run the function in m_name to decide if a type + /// matches or not. + lldb::FormatterMatchType m_match_type; // if the user tries to add formatters for, say, "struct Foo" those will not // match any type because of the way we strip qualifiers from typenames this @@ -71,24 +77,52 @@ public: TypeMatcher() = delete; /// Creates a matcher that accepts any type with exactly the given type name. TypeMatcher(ConstString type_name) - : m_type_name(type_name), m_is_regex(false) {} + : m_name(type_name), m_match_type(lldb::eFormatterMatchExact) {} /// Creates a matcher that accepts any type matching the given regex. TypeMatcher(RegularExpression regex) - : m_type_name_regex(std::move(regex)), m_is_regex(true) {} + : m_type_name_regex(std::move(regex)), + m_match_type(lldb::eFormatterMatchRegex) {} + /// Creates a matcher using the matching type and string from the given type + /// name specifier. + TypeMatcher(lldb::TypeNameSpecifierImplSP type_specifier) + : m_name(type_specifier->GetName()), + m_match_type(type_specifier->GetMatchType()) { + if (m_match_type == lldb::eFormatterMatchRegex) + m_type_name_regex = RegularExpression(type_specifier->GetName()); + } - /// True iff this matches the given type name. - bool Matches(ConstString type_name) const { - if (m_is_regex) + /// True iff this matches the given type. + bool Matches(FormattersMatchCandidate candidate_type) const { + ConstString type_name = candidate_type.GetTypeName(); + switch (m_match_type) { + case lldb::eFormatterMatchExact: + return m_name == type_name || + StripTypeName(m_name) == StripTypeName(type_name); + case lldb::eFormatterMatchRegex: return m_type_name_regex.Execute(type_name.GetStringRef()); - return m_type_name == type_name || - StripTypeName(m_type_name) == StripTypeName(type_name); + case lldb::eFormatterMatchCallback: + // CommandObjectType{Synth,Filter}Add tries to prevent the user from + // creating both a synthetic child provider and a filter for the same type + // in the same category, but we don't have a type object at that point, so + // it creates a dummy candidate without type or script interpreter. + // Skip callback matching in these cases. + if (candidate_type.GetScriptInterpreter()) + return candidate_type.GetScriptInterpreter()->FormatterCallbackFunction( + m_name.AsCString(), + std::make_shared(candidate_type.GetType())); + } + return false; } + lldb::FormatterMatchType GetMatchType() const { return m_match_type; } + /// Returns the underlying match string for this TypeMatcher. ConstString GetMatchString() const { - if (m_is_regex) - return ConstString(m_type_name_regex.GetText()); - return StripTypeName(m_type_name); + if (m_match_type == lldb::eFormatterMatchExact) + return StripTypeName(m_name); + if (m_match_type == lldb::eFormatterMatchRegex) + return ConstString(m_type_name_regex.GetText()); + return m_name; } /// Returns true if this TypeMatcher and the given one were most created by @@ -142,10 +176,11 @@ public: return false; } - bool Get(ConstString type, ValueSP &entry) { + // Finds the first formatter in the container that matches `candidate`. + bool Get(FormattersMatchCandidate candidate, ValueSP &entry) { std::lock_guard guard(m_map_mutex); for (auto &formatter : llvm::reverse(m_map)) { - if (formatter.first.Matches(type)) { + if (formatter.first.Matches(candidate)) { entry = formatter.second; return true; } @@ -153,6 +188,22 @@ public: return false; } + // Finds the first match between candidate types in `candidates` and + // formatters in this container. + bool Get(const FormattersMatchVector &candidates, ValueSP &entry) { + for (const FormattersMatchCandidate &candidate : candidates) { + if (Get(candidate, entry)) { + if (candidate.IsMatch(entry) == false) { + entry.reset(); + continue; + } else { + return true; + } + } + } + return false; + } + bool GetExact(TypeMatcher matcher, ValueSP &entry) { std::lock_guard guard(m_map_mutex); for (const auto &pos : m_map) @@ -176,7 +227,8 @@ public: return lldb::TypeNameSpecifierImplSP(); TypeMatcher type_matcher = m_map[index].first; return std::make_shared( - type_matcher.GetMatchString().GetStringRef(), true); + type_matcher.GetMatchString().GetStringRef(), + type_matcher.GetMatchType()); } void Clear() { @@ -213,20 +265,6 @@ protected: FormattersContainer(const FormattersContainer &) = delete; const FormattersContainer &operator=(const FormattersContainer &) = delete; - bool Get(const FormattersMatchVector &candidates, ValueSP &entry) { - for (const FormattersMatchCandidate &candidate : candidates) { - if (Get(candidate.GetTypeName(), entry)) { - if (candidate.IsMatch(entry) == false) { - entry.reset(); - continue; - } else { - return true; - } - } - } - return false; - } - MapType m_map; std::recursive_mutex m_map_mutex; IFormatChangeListener *listener; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersHelpers.h b/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersHelpers.h index 892807063b9..4f8f0e8455c 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersHelpers.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/FormattersHelpers.h @@ -56,7 +56,7 @@ void AddFilter(TypeCategoryImpl::SharedPointer category_sp, size_t ExtractIndexFromString(const char *item_name); -lldb::addr_t GetArrayAddressOrPointerValue(ValueObject &valobj); +Address GetArrayAddressOrPointerValue(ValueObject &valobj); lldb::ValueObjectSP GetValueOfLibCXXCompressedPair(ValueObject &pair); diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/StringPrinter.h b/gnu/llvm/lldb/include/lldb/DataFormatters/StringPrinter.h index 4a6e2e9051b..4169f53e63f 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/StringPrinter.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/StringPrinter.h @@ -12,9 +12,9 @@ #include #include -#include "lldb/lldb-forward.h" - +#include "lldb/Core/Address.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/lldb-forward.h" namespace lldb_private { namespace formatters { @@ -105,21 +105,21 @@ public: ReadStringAndDumpToStreamOptions(ValueObject &valobj); - void SetLocation(uint64_t l) { m_location = l; } + void SetLocation(Address l) { m_location = std::move(l); } - uint64_t GetLocation() const { return m_location; } + const Address &GetLocation() const { return m_location; } - void SetProcessSP(lldb::ProcessSP p) { m_process_sp = std::move(p); } + void SetTargetSP(lldb::TargetSP t) { m_target_sp = std::move(t); } - lldb::ProcessSP GetProcessSP() const { return m_process_sp; } + lldb::TargetSP GetTargetSP() const { return m_target_sp; } void SetHasSourceSize(bool e) { m_has_source_size = e; } bool HasSourceSize() const { return m_has_source_size; } private: - uint64_t m_location = 0; - lldb::ProcessSP m_process_sp; + Address m_location; + lldb::TargetSP m_target_sp; /// True iff we know the source size of the string. bool m_has_source_size = false; }; @@ -133,9 +133,9 @@ public: ReadBufferAndDumpToStreamOptions( const ReadStringAndDumpToStreamOptions &options); - void SetData(DataExtractor d) { m_data = d; } + void SetData(DataExtractor &&d) { m_data = std::move(d); } - lldb_private::DataExtractor GetData() const { return m_data; } + const lldb_private::DataExtractor &GetData() const { return m_data; } void SetIsTruncated(bool t) { m_is_truncated = t; } diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategory.h b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategory.h index 2c930590183..884a27d76e0 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategory.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategory.h @@ -9,6 +9,7 @@ #ifndef LLDB_DATAFORMATTERS_TYPECATEGORY_H #define LLDB_DATAFORMATTERS_TYPECATEGORY_H +#include #include #include #include @@ -23,225 +24,273 @@ namespace lldb_private { -template class FormatterContainerPair { +// A formatter container with sub-containers for different priority tiers, that +// also exposes a flat view of all formatters in it. +// +// Formatters have different priority during matching, depending on the type of +// matching specified at registration. Exact matchers are processed first, then +// regex, and finally callback matchers. However, the scripting API presents a +// flat view of formatters in a category, with methods like `GetNumFormats()` +// and `GetFormatAtIndex(i)`. So we need something that can behave like both +// representations. +template class TieredFormatterContainer { public: - typedef FormattersContainer ExactMatchContainer; - typedef FormattersContainer RegexMatchContainer; + using Subcontainer = FormattersContainer; + using SubcontainerSP = std::shared_ptr; + using ForEachCallback = typename Subcontainer::ForEachCallback; + using MapValueType = typename Subcontainer::ValueSP; + + TieredFormatterContainer(IFormatChangeListener *change_listener) { + for (auto& sc : m_subcontainers) + sc = std::make_shared(change_listener); + } - typedef TypeMatcher ExactMatchMap; - typedef TypeMatcher RegexMatchMap; + /// Clears all subcontainers. + void Clear() { + for (auto sc : m_subcontainers) + sc->Clear(); + } - typedef typename ExactMatchContainer::ValueSP MapValueType; + /// Adds a formatter to the right subcontainer depending on the matching type + /// specified by `type_sp`. + void Add(lldb::TypeNameSpecifierImplSP type_sp, + std::shared_ptr format_sp) { + m_subcontainers[type_sp->GetMatchType()]->Add(TypeMatcher(type_sp), + format_sp); + } - typedef typename ExactMatchContainer::SharedPointer ExactMatchContainerSP; - typedef typename RegexMatchContainer::SharedPointer RegexMatchContainerSP; + /// Deletes the formatter specified by `type_sp`. + bool Delete(lldb::TypeNameSpecifierImplSP type_sp) { + return m_subcontainers[type_sp->GetMatchType()]->Delete( + TypeMatcher(type_sp)); + } - typedef - typename ExactMatchContainer::ForEachCallback ExactMatchForEachCallback; - typedef - typename RegexMatchContainer::ForEachCallback RegexMatchForEachCallback; + /// Deletes all formatters registered with the string `name`, in all + /// subcontainers. + bool Delete(ConstString name) { + bool success = false; + for (auto sc : m_subcontainers) + success = sc->Delete(name) || success; + return success; + } - FormatterContainerPair(IFormatChangeListener *clist) - : m_exact_sp(new ExactMatchContainer(clist)), - m_regex_sp(new RegexMatchContainer(clist)) {} + /// Returns the total count of elements across all subcontainers. + uint32_t GetCount() { + uint32_t result = 0; + for (auto sc : m_subcontainers) + result += sc->GetCount(); + return result; + } - ~FormatterContainerPair() = default; + /// Returns the formatter at `index`, simulating a flattened view of all + /// subcontainers in priority order. + MapValueType GetAtIndex(size_t index) { + for (auto sc : m_subcontainers) { + if (index < sc->GetCount()) + return sc->GetAtIndex(index); + index -= sc->GetCount(); + } + return MapValueType(); + } - ExactMatchContainerSP GetExactMatch() const { return m_exact_sp; } + /// Looks for a matching candidate across all priority tiers, in priority + /// order. If a match is found, returns `true` and puts the matching entry in + /// `entry`. + bool Get(const FormattersMatchVector &candidates, + std::shared_ptr &entry) { + for (auto sc : m_subcontainers) { + if (sc->Get(candidates, entry)) + return true; + } + return false; + } - RegexMatchContainerSP GetRegexMatch() const { return m_regex_sp; } + bool AnyMatches(const FormattersMatchCandidate &candidate) { + std::shared_ptr entry; + for (auto sc : m_subcontainers) { + if (sc->Get(FormattersMatchVector{candidate}, entry)) + return true; + } + return false; + } - uint32_t GetCount() { - return GetExactMatch()->GetCount() + GetRegexMatch()->GetCount(); + /// Returns a formatter that is an exact match for `type_specifier_sp`. It + /// looks for a formatter with the same matching type that was created from + /// the same string. This is useful so we can refer to a formatter using the + /// same string used to register it. + /// + /// For example, `type_specifier_sp` can be something like + /// {"std::vector<.*>", eFormatterMatchRegex}, and we'd look for a regex + /// matcher with that exact regex string, NOT try to match that string using + /// regex. + MapValueType + GetForTypeNameSpecifier(lldb::TypeNameSpecifierImplSP type_specifier_sp) { + MapValueType retval; + if (type_specifier_sp) { + m_subcontainers[type_specifier_sp->GetMatchType()]->GetExact( + ConstString(type_specifier_sp->GetName()), retval); + } + return retval; } -private: - ExactMatchContainerSP m_exact_sp; - RegexMatchContainerSP m_regex_sp; + /// Returns the type name specifier at `index`, simulating a flattened view of + /// all subcontainers in priority order. + lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) { + for (auto sc : m_subcontainers) { + if (index < sc->GetCount()) + return sc->GetTypeNameSpecifierAtIndex(index); + index -= sc->GetCount(); + } + return lldb::TypeNameSpecifierImplSP(); + } + + /// Iterates through tiers in order, running `callback` on each element of + /// each tier. + void ForEach(std::function &)> + callback) { + for (auto sc : m_subcontainers) { + sc->ForEach(callback); + } + } + + void AutoComplete(CompletionRequest &request) { + for (auto sc: m_subcontainers) + sc->AutoComplete(request); + } + + private: + std::array, lldb::eLastFormatterMatchType + 1> + m_subcontainers; }; class TypeCategoryImpl { private: - typedef FormatterContainerPair FormatContainer; - typedef FormatterContainerPair SummaryContainer; - typedef FormatterContainerPair FilterContainer; - typedef FormatterContainerPair SynthContainer; + typedef TieredFormatterContainer FormatContainer; + typedef TieredFormatterContainer SummaryContainer; + typedef TieredFormatterContainer FilterContainer; + typedef TieredFormatterContainer SynthContainer; public: typedef uint16_t FormatCategoryItems; static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; - typedef FormatContainer::ExactMatchContainerSP FormatContainerSP; - typedef FormatContainer::RegexMatchContainerSP RegexFormatContainerSP; - - typedef SummaryContainer::ExactMatchContainerSP SummaryContainerSP; - typedef SummaryContainer::RegexMatchContainerSP RegexSummaryContainerSP; - - typedef FilterContainer::ExactMatchContainerSP FilterContainerSP; - typedef FilterContainer::RegexMatchContainerSP RegexFilterContainerSP; - - typedef SynthContainer::ExactMatchContainerSP SynthContainerSP; - typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP; - - template class ForEachCallbacks { - public: - ForEachCallbacks() = default; - ~ForEachCallbacks() = default; - - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetExact(FormatContainer::ExactMatchForEachCallback callback) { - m_format_exact = std::move(callback); - return *this; - } - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetWithRegex(FormatContainer::RegexMatchForEachCallback callback) { - m_format_regex = std::move(callback); - return *this; - } - - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetExact(SummaryContainer::ExactMatchForEachCallback callback) { - m_summary_exact = std::move(callback); - return *this; - } - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetWithRegex(SummaryContainer::RegexMatchForEachCallback callback) { - m_summary_regex = std::move(callback); - return *this; - } - - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetExact(FilterContainer::ExactMatchForEachCallback callback) { - m_filter_exact = std::move(callback); - return *this; - } - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetWithRegex(FilterContainer::RegexMatchForEachCallback callback) { - m_filter_regex = std::move(callback); - return *this; - } - - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetExact(SynthContainer::ExactMatchForEachCallback callback) { - m_synth_exact = std::move(callback); - return *this; - } - template - typename std::enable_if::value, ForEachCallbacks &>::type - SetWithRegex(SynthContainer::RegexMatchForEachCallback callback) { - m_synth_regex = std::move(callback); - return *this; - } - - FormatContainer::ExactMatchForEachCallback GetFormatExactCallback() const { - return m_format_exact; - } - FormatContainer::RegexMatchForEachCallback GetFormatRegexCallback() const { - return m_format_regex; - } + // TypeFilterImpl inherits from SyntheticChildren, so we can't simply overload + // ForEach on the type of the callback because it would result in "call to + // member function 'ForEach' is ambiguous" errors. Instead we use this + // templated struct to hold the formatter type and the callback. + template + struct ForEachCallback { + // Make it constructible from any callable that fits. This allows us to use + // lambdas a bit more easily at the call site. For example: + // ForEachCallback callback = [](...) {...}; + template ForEachCallback(Callable c) : callback(c) {} + std::function &)> + callback; + }; - SummaryContainer::ExactMatchForEachCallback - GetSummaryExactCallback() const { - return m_summary_exact; - } - SummaryContainer::RegexMatchForEachCallback - GetSummaryRegexCallback() const { - return m_summary_regex; - } + TypeCategoryImpl(IFormatChangeListener *clist, ConstString name); - FilterContainer::ExactMatchForEachCallback GetFilterExactCallback() const { - return m_filter_exact; - } - FilterContainer::RegexMatchForEachCallback GetFilterRegexCallback() const { - return m_filter_regex; - } + void ForEach(ForEachCallback callback) { + m_format_cont.ForEach(callback.callback); + } - SynthContainer::ExactMatchForEachCallback GetSynthExactCallback() const { - return m_synth_exact; - } - SynthContainer::RegexMatchForEachCallback GetSynthRegexCallback() const { - return m_synth_regex; - } + void ForEach(ForEachCallback callback) { + m_summary_cont.ForEach(callback.callback); + } - private: - FormatContainer::ExactMatchForEachCallback m_format_exact; - FormatContainer::RegexMatchForEachCallback m_format_regex; + void ForEach(ForEachCallback callback) { + m_filter_cont.ForEach(callback.callback); + } - SummaryContainer::ExactMatchForEachCallback m_summary_exact; - SummaryContainer::RegexMatchForEachCallback m_summary_regex; + void ForEach(ForEachCallback callback) { + m_synth_cont.ForEach(callback.callback); + } - FilterContainer::ExactMatchForEachCallback m_filter_exact; - FilterContainer::RegexMatchForEachCallback m_filter_regex; + FormatContainer::MapValueType + GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp); - SynthContainer::ExactMatchForEachCallback m_synth_exact; - SynthContainer::RegexMatchForEachCallback m_synth_regex; - }; + SummaryContainer::MapValueType + GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp); - TypeCategoryImpl(IFormatChangeListener *clist, ConstString name); + FilterContainer::MapValueType + GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp); - template void ForEach(const ForEachCallbacks &foreach) { - GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback()); - GetRegexTypeFormatsContainer()->ForEach(foreach.GetFormatRegexCallback()); + SynthContainer::MapValueType + GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp); - GetTypeSummariesContainer()->ForEach(foreach.GetSummaryExactCallback()); - GetRegexTypeSummariesContainer()->ForEach( - foreach.GetSummaryRegexCallback()); + void AddTypeFormat(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeFormatImplSP format_sp) { + m_format_cont.Add(type_sp, format_sp); + } - GetTypeFiltersContainer()->ForEach(foreach.GetFilterExactCallback()); - GetRegexTypeFiltersContainer()->ForEach(foreach.GetFilterRegexCallback()); + void AddTypeFormat(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeFormatImplSP format_sp) { + AddTypeFormat( + std::make_shared(name, match_type), + format_sp); + } - GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback()); - GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback()); + void AddTypeSummary(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeSummaryImplSP summary_sp) { + m_summary_cont.Add(type_sp, summary_sp); } - FormatContainerSP GetTypeFormatsContainer() { - return m_format_cont.GetExactMatch(); + void AddTypeSummary(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeSummaryImplSP summary_sp) { + AddTypeSummary( + std::make_shared(name, match_type), + summary_sp); } - RegexFormatContainerSP GetRegexTypeFormatsContainer() { - return m_format_cont.GetRegexMatch(); + void AddTypeFilter(lldb::TypeNameSpecifierImplSP type_sp, + lldb::TypeFilterImplSP filter_sp) { + m_filter_cont.Add(type_sp, filter_sp); } - FormatContainer &GetFormatContainer() { return m_format_cont; } + void AddTypeFilter(llvm::StringRef name, lldb::FormatterMatchType match_type, + lldb::TypeFilterImplSP filter_sp) { + AddTypeFilter( + std::make_shared(name, match_type), + filter_sp); + } - SummaryContainerSP GetTypeSummariesContainer() { - return m_summary_cont.GetExactMatch(); + void AddTypeSynthetic(lldb::TypeNameSpecifierImplSP type_sp, + lldb::SyntheticChildrenSP synth_sp) { + m_synth_cont.Add(type_sp, synth_sp); } - RegexSummaryContainerSP GetRegexTypeSummariesContainer() { - return m_summary_cont.GetRegexMatch(); + void AddTypeSynthetic(llvm::StringRef name, + lldb::FormatterMatchType match_type, + lldb::SyntheticChildrenSP synth_sp) { + AddTypeSynthetic( + std::make_shared(name, match_type), + synth_sp); } - SummaryContainer &GetSummaryContainer() { return m_summary_cont; } + bool DeleteTypeFormat(lldb::TypeNameSpecifierImplSP type_sp) { + return m_format_cont.Delete(type_sp); + } - FilterContainerSP GetTypeFiltersContainer() { - return m_filter_cont.GetExactMatch(); + bool DeleteTypeSummary(lldb::TypeNameSpecifierImplSP type_sp) { + return m_summary_cont.Delete(type_sp); } - RegexFilterContainerSP GetRegexTypeFiltersContainer() { - return m_filter_cont.GetRegexMatch(); + bool DeleteTypeFilter(lldb::TypeNameSpecifierImplSP type_sp) { + return m_filter_cont.Delete(type_sp); } - FilterContainer &GetFilterContainer() { return m_filter_cont; } + bool DeleteTypeSynthetic(lldb::TypeNameSpecifierImplSP type_sp) { + return m_synth_cont.Delete(type_sp); + } - FormatContainer::MapValueType - GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumFormats() { return m_format_cont.GetCount(); } - SummaryContainer::MapValueType - GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumSummaries() { return m_summary_cont.GetCount(); } - FilterContainer::MapValueType - GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumFilters() { return m_filter_cont.GetCount(); } - SynthContainer::MapValueType - GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp); + uint32_t GetNumSynthetics() { return m_synth_cont.GetCount(); } lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForFormatAtIndex(size_t index); @@ -249,30 +298,20 @@ public: lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForSummaryAtIndex(size_t index); - FormatContainer::MapValueType GetFormatAtIndex(size_t index); - - SummaryContainer::MapValueType GetSummaryAtIndex(size_t index); - - FilterContainer::MapValueType GetFilterAtIndex(size_t index); - lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForFilterAtIndex(size_t index); - SynthContainerSP GetTypeSyntheticsContainer() { - return m_synth_cont.GetExactMatch(); - } + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForSyntheticAtIndex(size_t index); - RegexSynthContainerSP GetRegexTypeSyntheticsContainer() { - return m_synth_cont.GetRegexMatch(); - } + FormatContainer::MapValueType GetFormatAtIndex(size_t index); + + SummaryContainer::MapValueType GetSummaryAtIndex(size_t index); - SynthContainer &GetSyntheticsContainer() { return m_synth_cont; } + FilterContainer::MapValueType GetFilterAtIndex(size_t index); SynthContainer::MapValueType GetSyntheticAtIndex(size_t index); - lldb::TypeNameSpecifierImplSP - GetTypeNameSpecifierForSyntheticAtIndex(size_t index); - bool IsEnabled() const { return m_enabled; } uint32_t GetEnabledPosition() { @@ -307,12 +346,14 @@ public: std::string GetDescription(); - bool AnyMatches(ConstString type_name, + bool AnyMatches(const FormattersMatchCandidate &candidate_type, FormatCategoryItems items = ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, FormatCategoryItems *matching_type = nullptr); + void AutoComplete(CompletionRequest &request, FormatCategoryItems items); + typedef std::shared_ptr SharedPointer; private: @@ -331,7 +372,7 @@ private: std::vector m_languages; - uint32_t m_enabled_position; + uint32_t m_enabled_position = 0; void Enable(bool value, uint32_t position); diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategoryMap.h b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategoryMap.h index 4dbca29db06..d4f7634c90b 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategoryMap.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeCategoryMap.h @@ -17,19 +17,20 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" +#include "lldb/DataFormatters/FormatClasses.h" #include "lldb/DataFormatters/FormattersContainer.h" #include "lldb/DataFormatters/TypeCategory.h" namespace lldb_private { class TypeCategoryMap { private: - typedef ConstString KeyType; - typedef TypeCategoryImpl ValueType; - typedef ValueType::SharedPointer ValueSP; typedef std::list ActiveCategoriesList; typedef ActiveCategoriesList::iterator ActiveCategoriesIterator; public: + typedef ConstString KeyType; + typedef TypeCategoryImpl ValueType; + typedef ValueType::SharedPointer ValueSP; typedef std::map MapType; typedef MapType::iterator MapIterator; typedef std::function ForEachCallback; @@ -69,7 +70,7 @@ public: lldb::TypeCategoryImplSP GetAtIndex(uint32_t); bool - AnyMatches(ConstString type_name, + AnyMatches(const FormattersMatchCandidate &candidate_type, TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, bool only_enabled = true, const char **matching_category = nullptr, @@ -103,9 +104,6 @@ private: ActiveCategoriesList &active_list() { return m_active_categories; } std::recursive_mutex &mutex() { return m_map_mutex; } - - friend class FormattersContainer; - friend class FormatManager; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSummary.h b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSummary.h index 30bc8cbf3fe..a82641021da 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSummary.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSummary.h @@ -263,7 +263,7 @@ public: typedef std::shared_ptr SharedPointer; protected: - uint32_t m_my_revision; + uint32_t m_my_revision = 0; Flags m_flags; TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags); diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSynthetic.h index 24322bd51a0..890a6eb4f44 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSynthetic.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/TypeSynthetic.h @@ -266,7 +266,7 @@ public: uint32_t &GetRevision() { return m_my_revision; } protected: - uint32_t m_my_revision; + uint32_t m_my_revision = 0; Flags m_flags; private: @@ -279,11 +279,11 @@ class TypeFilterImpl : public SyntheticChildren { public: TypeFilterImpl(const SyntheticChildren::Flags &flags) - : SyntheticChildren(flags), m_expression_paths() {} + : SyntheticChildren(flags) {} TypeFilterImpl(const SyntheticChildren::Flags &flags, const std::initializer_list items) - : SyntheticChildren(flags), m_expression_paths() { + : SyntheticChildren(flags) { for (auto path : items) AddExpressionPath(path); } @@ -391,7 +391,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren { public: ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags, const char *pclass, const char *pcode = nullptr) - : SyntheticChildren(flags), m_python_class(), m_python_code() { + : SyntheticChildren(flags) { if (pclass) m_python_class = pclass; if (pcode) diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/gnu/llvm/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h index 833cd5eea35..90e54021a71 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -117,6 +117,8 @@ protected: bool PrintChildrenOneLiner(bool hide_names); + bool HasReachedMaximumDepth(); + private: ValueObject *m_orig_valobj; ValueObject *m_valobj; diff --git a/gnu/llvm/lldb/include/lldb/DataFormatters/VectorIterator.h b/gnu/llvm/lldb/include/lldb/DataFormatters/VectorIterator.h index 33650a3dac8..3414298f255 100644 --- a/gnu/llvm/lldb/include/lldb/DataFormatters/VectorIterator.h +++ b/gnu/llvm/lldb/include/lldb/DataFormatters/VectorIterator.h @@ -15,13 +15,14 @@ #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Utility/ConstString.h" +#include "llvm/ADT/SmallVector.h" namespace lldb_private { namespace formatters { class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp, - ConstString item_name); + llvm::ArrayRef item_names); size_t CalculateNumChildren() override; @@ -35,7 +36,7 @@ public: private: ExecutionContextRef m_exe_ctx_ref; - ConstString m_item_name; + llvm::SmallVector m_item_names; lldb::ValueObjectSP m_item_sp; }; diff --git a/gnu/llvm/lldb/include/lldb/Expression/DWARFExpression.h b/gnu/llvm/lldb/include/lldb/Expression/DWARFExpression.h index 1490ac2d614..aea41926d84 100644 --- a/gnu/llvm/lldb/include/lldb/Expression/DWARFExpression.h +++ b/gnu/llvm/lldb/include/lldb/Expression/DWARFExpression.h @@ -15,6 +15,7 @@ #include "lldb/Utility/Scalar.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private.h" +#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include class DWARFUnit; @@ -41,57 +42,14 @@ public: /// \param[in] data /// A data extractor configured to read the DWARF location expression's /// bytecode. - DWARFExpression(lldb::ModuleSP module, const DataExtractor &data, - const DWARFUnit *dwarf_cu); + DWARFExpression(const DataExtractor &data); /// Destructor virtual ~DWARFExpression(); - /// Print the description of the expression to a stream - /// - /// \param[in] s - /// The stream to print to. - /// - /// \param[in] level - /// The level of verbosity to use. - /// - /// \param[in] location_list_base_addr - /// If this is a location list based expression, this is the - /// address of the object that owns it. NOTE: this value is - /// different from the DWARF version of the location list base - /// address which is compile unit relative. This base address - /// is the address of the object that owns the location list. - /// - /// \param[in] abi - /// An optional ABI plug-in that can be used to resolve register - /// names. - void GetDescription(Stream *s, lldb::DescriptionLevel level, - lldb::addr_t location_list_base_addr, ABI *abi) const; - /// Return true if the location expression contains data bool IsValid() const; - /// Return true if a location list was provided - bool IsLocationList() const; - - /// Search for a load address in the location list - /// - /// \param[in] func_load_addr - /// The actual address of the function containing this location list. - /// - /// \param[in] addr - /// The address to resolve - /// - /// \return - /// True if IsLocationList() is true and the address was found; - /// false otherwise. - // bool - // LocationListContainsLoadAddress (Process* process, const Address &addr) - // const; - // - bool LocationListContainsAddress(lldb::addr_t func_load_addr, - lldb::addr_t addr) const; - /// If a location is not a location list, return true if the location /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr. /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true @@ -100,6 +58,9 @@ public: /// static variable since there is no other indication from DWARF debug /// info. /// + /// \param[in] dwarf_cu + /// The dwarf unit this expression belongs to. + /// /// \param[in] op_addr_idx /// The DW_OP_addr index to retrieve in case there is more than /// one DW_OP_addr opcode in the location byte stream. @@ -111,36 +72,23 @@ public: /// \return /// LLDB_INVALID_ADDRESS if the location doesn't contain a /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address - lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const; + lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, + uint32_t op_addr_idx, bool &error) const; - bool Update_DW_OP_addr(lldb::addr_t file_addr); + bool Update_DW_OP_addr(const DWARFUnit *dwarf_cu, lldb::addr_t file_addr); void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size, uint8_t addr_byte_size); - void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } - - bool ContainsThreadLocalStorage() const; + bool ContainsThreadLocalStorage(const DWARFUnit *dwarf_cu) const; bool LinkThreadLocalStorage( - lldb::ModuleSP new_module_sp, + const DWARFUnit *dwarf_cu, std::function const &link_address_callback); - /// Tells the expression that it refers to a location list. - /// - /// \param[in] cu_file_addr - /// The base address to use for interpreting relative location list - /// entries. - /// \param[in] func_file_addr - /// The file address of the function containing this location list. This - /// address will be used to relocate the location list on the fly (in - /// conjuction with the func_load_addr arguments). - void SetLocationListAddresses(lldb::addr_t cu_file_addr, - lldb::addr_t func_file_addr); - /// Return the call-frame-info style register kind - int GetRegisterKind(); + lldb::RegisterKind GetRegisterKind() const; /// Set the call-frame-info style register kind /// @@ -148,20 +96,6 @@ public: /// The register kind. void SetRegisterKind(lldb::RegisterKind reg_kind); - /// Wrapper for the static evaluate function that accepts an - /// ExecutionContextScope instead of an ExecutionContext and uses member - /// variables to populate many operands - bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr, - const Value *initial_value_ptr, const Value *object_address_ptr, - Value &result, Status *error_ptr) const; - - /// Wrapper for the static evaluate function that uses member variables to - /// populate many operands - bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, - lldb::addr_t loclist_base_load_addr, - const Value *initial_value_ptr, const Value *object_address_ptr, - Value &result, Status *error_ptr) const; - /// Evaluate a DWARF location expression in a particular context /// /// \param[in] exe_ctx @@ -201,65 +135,32 @@ public: /// True on success; false otherwise. If error_ptr is non-NULL, /// details of the failure are provided through it. static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, - lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes, + lldb::ModuleSP module_sp, const DataExtractor &opcodes, const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr); + static bool ParseDWARFLocationList(const DWARFUnit *dwarf_cu, + const DataExtractor &data, + DWARFExpressionList *loc_list); + bool GetExpressionData(DataExtractor &data) const { data = m_data; return data.GetByteSize() > 0; } - bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level, - lldb::addr_t func_load_addr, lldb::addr_t address, - ABI *abi); + void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; - bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); - - llvm::Optional - GetLocationExpression(lldb::addr_t load_function_start, - lldb::addr_t addr) const; + bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const; private: - /// Pretty-prints the location expression to a stream - /// - /// \param[in] s - /// The stream to use for pretty-printing. - /// - /// \param[in] data - /// The data extractor. - /// - /// \param[in] level - /// The level of detail to use in pretty-printing. - /// - /// \param[in] abi - /// An optional ABI plug-in that can be used to resolve register - /// names. - void DumpLocation(Stream *s, const DataExtractor &data, - lldb::DescriptionLevel level, ABI *abi) const; - - /// Module which defined this expression. - lldb::ModuleWP m_module_wp; - /// A data extractor capable of reading opcode bytes DataExtractor m_data; - /// 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) - const DWARFUnit *m_dwarf_cu = nullptr; - /// One of the defines that starts with LLDB_REGKIND_ lldb::RegisterKind m_reg_kind = lldb::eRegisterKindDWARF; - - struct LoclistAddresses { - lldb::addr_t cu_file_addr; - lldb::addr_t func_file_addr; - }; - llvm::Optional m_loclist_addresses; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Expression/DWARFExpressionList.h b/gnu/llvm/lldb/include/lldb/Expression/DWARFExpressionList.h new file mode 100644 index 00000000000..c0939647056 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Expression/DWARFExpressionList.h @@ -0,0 +1,150 @@ +//===-- DWARFExpressionList.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H +#define LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H + +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Utility/RangeMap.h" +#include "lldb/lldb-private.h" + +class DWARFUnit; + +namespace lldb_private { + +/// \class DWARFExpressionList DWARFExpressionList.h +/// "lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file +/// address range to a single DWARF location expression. +class DWARFExpressionList { +public: + DWARFExpressionList() = default; + + DWARFExpressionList(lldb::ModuleSP module_sp, const DWARFUnit *dwarf_cu, + lldb::addr_t func_file_addr) + : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu), + m_func_file_addr(func_file_addr) {} + + DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr, + const DWARFUnit *dwarf_cu) + : m_module_wp(module_sp), m_dwarf_cu(dwarf_cu) { + AddExpression(0, LLDB_INVALID_ADDRESS, expr); + } + + /// Return true if the location expression contains data + bool IsValid() const { return !m_exprs.IsEmpty(); } + + void Clear() { m_exprs.Clear(); } + + // Return true if the location expression is always valid. + bool IsAlwaysValidSingleExpr() const; + + bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr); + + /// Get the expression data at the file address. + bool GetExpressionData(DataExtractor &data, + lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t file_addr = 0) const; + + /// Sort m_expressions. + void Sort() { m_exprs.Sort(); } + + void SetFuncFileAddress(lldb::addr_t func_file_addr) { + m_func_file_addr = func_file_addr; + } + + lldb::addr_t GetFuncFileAddress() { return m_func_file_addr; } + + const DWARFExpression *GetExpressionAtAddress(lldb::addr_t func_load_addr, + lldb::addr_t load_addr) const; + + const DWARFExpression *GetAlwaysValidExpr() const; + + DWARFExpression *GetMutableExpressionAtAddress( + lldb::addr_t func_load_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t load_addr = 0); + + size_t GetSize() const { return m_exprs.GetSize(); } + + bool ContainsThreadLocalStorage() const; + + bool LinkThreadLocalStorage( + lldb::ModuleSP new_module_sp, + std::function const + &link_address_callback); + + bool MatchesOperand(StackFrame &frame, + const Instruction::Operand &operand) const; + + /// Dump locations that contains file_addr if it's valid. Otherwise. dump all + /// locations. + bool DumpLocations(Stream *s, lldb::DescriptionLevel level, + lldb::addr_t func_load_addr, lldb::addr_t file_addr, + ABI *abi) const; + + /// Dump all locaitons with each seperated by new line. + void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const; + + /// Search for a load address in the dwarf location list + /// + /// \param[in] func_load_addr + /// The actual address of the function containing this location list. + /// + /// \param[in] addr + /// The address to resolve. + /// + /// \return + /// True if IsLocationList() is true and the address was found; + /// false otherwise. + // bool + // LocationListContainsLoadAddress (Process* process, const Address &addr) + // const; + // + bool ContainsAddress(lldb::addr_t func_load_addr, lldb::addr_t addr) const; + + void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } + + bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, + lldb::addr_t func_load_addr, const Value *initial_value_ptr, + const Value *object_address_ptr, Value &result, + Status *error_ptr) const; + +private: + // RangeDataVector requires a comparator for DWARFExpression, but it doesn't + // make sense to do so. + struct DWARFExpressionCompare { + public: + bool operator()(const DWARFExpression &lhs, + const DWARFExpression &rhs) const { + return false; + } + }; + using ExprVec = RangeDataVector; + using Entry = ExprVec::Entry; + + // File address range mapping to single dwarf expression. + ExprVec m_exprs; + + /// Module which defined this expression. + lldb::ModuleWP m_module_wp; + + /// 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) + const DWARFUnit *m_dwarf_cu = nullptr; + + // Function base file address. + lldb::addr_t m_func_file_addr = LLDB_INVALID_ADDRESS; + + using const_iterator = ExprVec::Collection::const_iterator; + const_iterator begin() const { return m_exprs.begin(); } + const_iterator end() const { return m_exprs.end(); } +}; +} // namespace lldb_private + +#endif // LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H diff --git a/gnu/llvm/lldb/include/lldb/Expression/ExpressionVariable.h b/gnu/llvm/lldb/include/lldb/Expression/ExpressionVariable.h index de700b67661..27343530780 100644 --- a/gnu/llvm/lldb/include/lldb/Expression/ExpressionVariable.h +++ b/gnu/llvm/lldb/include/lldb/Expression/ExpressionVariable.h @@ -10,6 +10,7 @@ #define LLDB_EXPRESSION_EXPRESSIONVARIABLE_H #include +#include #include #include "llvm/ADT/DenseMap.h" @@ -32,7 +33,7 @@ public: virtual ~ExpressionVariable(); - llvm::Optional GetByteSize() { return m_frozen_sp->GetByteSize(); } + std::optional GetByteSize() { return m_frozen_sp->GetByteSize(); } ConstString GetName() { return m_frozen_sp->GetName(); } @@ -226,7 +227,7 @@ public: virtual void RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; - virtual llvm::Optional + virtual std::optional GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; virtual lldb::addr_t LookupSymbol(ConstString name); diff --git a/gnu/llvm/lldb/include/lldb/Expression/IRExecutionUnit.h b/gnu/llvm/lldb/include/lldb/Expression/IRExecutionUnit.h index ad3c7372e67..ef53ca512d7 100644 --- a/gnu/llvm/lldb/include/lldb/Expression/IRExecutionUnit.h +++ b/gnu/llvm/lldb/include/lldb/Expression/IRExecutionUnit.h @@ -214,26 +214,21 @@ private: Status DisassembleFunction(Stream &stream, lldb::ProcessSP &process_sp); - struct SearchSpec; - - void CollectCandidateCNames(std::vector &C_specs, + void CollectCandidateCNames(std::vector &C_names, ConstString name); - void CollectCandidateCPlusPlusNames(std::vector &CPP_specs, - const std::vector &C_specs, + void CollectCandidateCPlusPlusNames(std::vector &CPP_names, + const std::vector &C_names, const SymbolContext &sc); - void CollectFallbackNames(std::vector &fallback_specs, - const std::vector &C_specs); - - lldb::addr_t FindInSymbols(const std::vector &specs, + lldb::addr_t FindInSymbols(const std::vector &names, const lldb_private::SymbolContext &sc, bool &symbol_was_missing_weak); - lldb::addr_t FindInRuntimes(const std::vector &specs, + lldb::addr_t FindInRuntimes(const std::vector &names, const lldb_private::SymbolContext &sc); - lldb::addr_t FindInUserDefinedSymbols(const std::vector &specs, + lldb::addr_t FindInUserDefinedSymbols(const std::vector &names, const lldb_private::SymbolContext &sc); void ReportSymbolLookupError(ConstString name); @@ -352,10 +347,9 @@ private: AllocationRecord(uintptr_t host_address, uint32_t permissions, lldb::SectionType sect_type, size_t size, unsigned alignment, unsigned section_id, const char *name) - : m_name(), m_process_address(LLDB_INVALID_ADDRESS), - m_host_address(host_address), m_permissions(permissions), - m_sect_type(sect_type), m_size(size), m_alignment(alignment), - m_section_id(section_id) { + : m_process_address(LLDB_INVALID_ADDRESS), m_host_address(host_address), + m_permissions(permissions), m_sect_type(sect_type), m_size(size), + m_alignment(alignment), m_section_id(section_id) { if (name && name[0]) m_name = name; } diff --git a/gnu/llvm/lldb/include/lldb/Expression/Materializer.h b/gnu/llvm/lldb/include/lldb/Expression/Materializer.h index 25cf22a8b5b..aae94f86a71 100644 --- a/gnu/llvm/lldb/include/lldb/Expression/Materializer.h +++ b/gnu/llvm/lldb/include/lldb/Expression/Materializer.h @@ -78,6 +78,28 @@ public: AddPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, PersistentVariableDelegate *delegate, Status &err); uint32_t AddVariable(lldb::VariableSP &variable_sp, Status &err); + + /// Create entity from supplied ValueObject and count it as a member + /// of the materialized struct. + /// + /// Behaviour is undefined if 'valobj_provider' is empty. + /// + /// \param[in] name Name of variable to materialize + /// + /// \param[in] valobj_provider When materializing values multiple + /// times, this callback gets used to fetch a fresh + /// ValueObject corresponding to the supplied frame. + /// This is mainly used for conditional breakpoints + /// that re-apply an expression whatever the frame + /// happens to be when the breakpoint got hit. + /// + /// \param[out] err Error status that gets set on error. + /// + /// \returns Offset in bytes of the member we just added to the + /// materialized struct. + uint32_t AddValueObject(ConstString name, + ValueObjectProviderTy valobj_provider, Status &err); + uint32_t AddResultVariable(const CompilerType &type, bool is_lvalue, bool keep_in_memory, PersistentVariableDelegate *delegate, Status &err); diff --git a/gnu/llvm/lldb/include/lldb/Expression/UserExpression.h b/gnu/llvm/lldb/include/lldb/Expression/UserExpression.h index 8236c417f73..2d62fa37a24 100644 --- a/gnu/llvm/lldb/include/lldb/Expression/UserExpression.h +++ b/gnu/llvm/lldb/include/lldb/Expression/UserExpression.h @@ -266,10 +266,8 @@ public: 0x1001; ///< ValueObject::GetError() returns this if there is no result /// from the expression. - const char *GetFixedText() { - if (m_fixed_text.empty()) - return nullptr; - return m_fixed_text.c_str(); + llvm::StringRef GetFixedText() { + return m_fixed_text; } protected: @@ -282,6 +280,23 @@ protected: static lldb::addr_t GetObjectPointer(lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err); + /// Return ValueObject for a given variable name in the current stack frame + /// + /// \param[in] frame Current stack frame. When passed a 'nullptr', this + /// function returns an empty ValueObjectSP. + /// + /// \param[in] object_name Name of the variable in the current stack frame + /// for which we want the ValueObjectSP. + /// + /// \param[out] err Status object which will get set on error. + /// + /// \returns On success returns a ValueObjectSP corresponding to the variable + /// with 'object_name' in the current 'frame'. Otherwise, returns + /// 'nullptr' (and sets the error status parameter 'err'). + static lldb::ValueObjectSP + GetObjectPointerValueObject(lldb::StackFrameSP frame, + ConstString const &object_name, Status &err); + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the /// environment. diff --git a/gnu/llvm/lldb/include/lldb/Host/Config.h.cmake b/gnu/llvm/lldb/include/lldb/Host/Config.h.cmake index c667708a90a..14ce46f6559 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Config.h.cmake +++ b/gnu/llvm/lldb/include/lldb/Host/Config.h.cmake @@ -13,17 +13,12 @@ #cmakedefine01 LLDB_HAVE_EL_RFUNC_T - -#cmakedefine01 HAVE_SYS_TYPES_H - #cmakedefine01 HAVE_SYS_EVENT_H #cmakedefine01 HAVE_PPOLL #cmakedefine01 HAVE_PTSNAME_R -#cmakedefine01 HAVE_SIGACTION - #cmakedefine01 HAVE_PROCESS_VM_READV #cmakedefine01 HAVE_NR_PROCESS_VM_READV @@ -50,10 +45,14 @@ #cmakedefine01 LLDB_ENABLE_PYTHON +#cmakedefine01 LLDB_ENABLE_FBSDVMCORE + #cmakedefine01 LLDB_EMBED_PYTHON_HOME #cmakedefine LLDB_PYTHON_HOME R"(${LLDB_PYTHON_HOME})" -#define LLDB_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" +#define LLDB_INSTALL_LIBDIR_BASENAME "${LLDB_INSTALL_LIBDIR_BASENAME}" + +#cmakedefine LLDB_GLOBAL_INIT_DIRECTORY R"(${LLDB_GLOBAL_INIT_DIRECTORY})" #endif // #ifndef LLDB_HOST_CONFIG_H diff --git a/gnu/llvm/lldb/include/lldb/Host/Debug.h b/gnu/llvm/lldb/include/lldb/Host/Debug.h index 7da59dd04a6..56a6efd1b4d 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Debug.h +++ b/gnu/llvm/lldb/include/lldb/Host/Debug.h @@ -32,15 +32,13 @@ struct ResumeAction { // send a signal to the thread when the action is run or step. class ResumeActionList { public: - ResumeActionList() : m_actions(), m_signal_handled() {} + ResumeActionList() = default; - ResumeActionList(lldb::StateType default_action, int signal) - : m_actions(), m_signal_handled() { + ResumeActionList(lldb::StateType default_action, int signal) { SetDefaultThreadActionIfNeeded(default_action, signal); } - ResumeActionList(const ResumeAction *actions, size_t num_actions) - : m_actions(), m_signal_handled() { + ResumeActionList(const ResumeAction *actions, size_t num_actions) { if (actions && num_actions) { m_actions.assign(actions, actions + num_actions); m_signal_handled.assign(num_actions, false); @@ -132,12 +130,8 @@ protected: struct ThreadStopInfo { lldb::StopReason reason; + uint32_t signo; union { - // eStopReasonSignal - struct { - uint32_t signo; - } signal; - // eStopReasonException struct { uint64_t type; diff --git a/gnu/llvm/lldb/include/lldb/Host/Editline.h b/gnu/llvm/lldb/include/lldb/Host/Editline.h index 876f6052311..bda3f06d894 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Editline.h +++ b/gnu/llvm/lldb/include/lldb/Host/Editline.h @@ -46,6 +46,7 @@ #include #include +#include #include #include @@ -98,7 +99,7 @@ using FixIndentationCallbackType = llvm::unique_function; using SuggestionCallbackType = - llvm::unique_function(llvm::StringRef)>; + llvm::unique_function(llvm::StringRef)>; using CompleteCallbackType = llvm::unique_function; @@ -154,7 +155,8 @@ using namespace line_editor; class Editline { public: Editline(const char *editor_name, FILE *input_file, FILE *output_file, - FILE *error_file, bool color_prompts); + FILE *error_file, std::recursive_mutex &output_mutex, + bool color_prompts); ~Editline(); @@ -210,6 +212,14 @@ public: m_fix_indentation_callback_chars = indent_chars; } + void SetSuggestionAnsiPrefix(std::string prefix) { + m_suggestion_ansi_prefix = std::move(prefix); + } + + void SetSuggestionAnsiSuffix(std::string suffix) { + m_suggestion_ansi_suffix = std::move(suffix); + } + /// Prompts for and reads a single line of user input. bool GetLine(std::string &line, bool &interrupted); @@ -388,11 +398,13 @@ private: const char *m_fix_indentation_callback_chars = nullptr; CompleteCallbackType m_completion_callback; - SuggestionCallbackType m_suggestion_callback; + std::string m_suggestion_ansi_prefix; + std::string m_suggestion_ansi_suffix; + std::size_t m_previous_autosuggestion_size = 0; - std::mutex m_output_mutex; + std::recursive_mutex &m_output_mutex; }; } diff --git a/gnu/llvm/lldb/include/lldb/Host/File.h b/gnu/llvm/lldb/include/lldb/Host/File.h index d364d954a1c..a1199a51b8a 100644 --- a/gnu/llvm/lldb/include/lldb/Host/File.h +++ b/gnu/llvm/lldb/include/lldb/Host/File.h @@ -10,6 +10,7 @@ #define LLDB_HOST_FILE_H #include "lldb/Host/PosixApi.h" +#include "lldb/Host/Terminal.h" #include "lldb/Utility/IOObject.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private.h" @@ -18,6 +19,7 @@ #include #include #include +#include #include namespace lldb_private { @@ -39,24 +41,29 @@ public: // NB this enum is used in the lldb platform gdb-remote packet // vFile:open: and existing values cannot be modified. // - // FIXME - // These values do not match the values used by GDB + // The first set of values is defined by gdb headers and can be found + // in the documentation at: // * https://sourceware.org/gdb/onlinedocs/gdb/Open-Flags.html#Open-Flags - // * rdar://problem/46788934 + // + // The second half are LLDB extensions and use the highest uint32_t bits + // to avoid risk of collisions with future gdb remote protocol changes. enum OpenOptions : uint32_t { - eOpenOptionRead = (1u << 0), // Open file for reading - eOpenOptionWrite = (1u << 1), // Open file for writing + eOpenOptionReadOnly = 0x0, // Open file for reading (only) + eOpenOptionWriteOnly = 0x1, // Open file for writing (only) + eOpenOptionReadWrite = 0x2, // Open file for both reading and writing eOpenOptionAppend = - (1u << 2), // Don't truncate file when opening, append to end of file - eOpenOptionTruncate = (1u << 3), // Truncate file when opening - eOpenOptionNonBlocking = (1u << 4), // File reads - eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist + 0x8, // Don't truncate file when opening, append to end of file + eOpenOptionCanCreate = 0x200, // Create file if doesn't already exist + eOpenOptionTruncate = 0x400, // Truncate file when opening eOpenOptionCanCreateNewOnly = - (1u << 6), // Can create file only if it doesn't already exist - eOpenOptionDontFollowSymlinks = (1u << 7), + 0x800, // Can create file only if it doesn't already exist + + eOpenOptionNonBlocking = (1u << 28), // File reads + eOpenOptionDontFollowSymlinks = (1u << 29), eOpenOptionCloseOnExec = - (1u << 8), // Close the file when executing a new process - LLVM_MARK_AS_BITMASK_ENUM(/* largest_value= */ eOpenOptionCloseOnExec) + (1u << 30), // Close the file when executing a new process + eOpenOptionInvalid = (1u << 31), // Used as invalid value + LLVM_MARK_AS_BITMASK_ENUM(/* largest_value= */ eOpenOptionInvalid) }; static mode_t ConvertOpenOptionsForPOSIXOpen(OpenOptions open_options); @@ -219,7 +226,7 @@ public: /// A buffer where to put the bytes that are read. /// /// \param[in,out] num_bytes - /// The number of bytes to read form the current file position + /// The number of bytes to read from the current file position /// which gets modified with the number of bytes that were read. /// /// \param[in,out] offset @@ -303,8 +310,8 @@ public: /// Some options like eOpenOptionDontFollowSymlinks only make /// sense when a file is being opened (or not at all) /// and may not be preserved for this method. But any valid - /// File should return either or both of eOpenOptionRead and - /// eOpenOptionWrite here. + /// File should return either eOpenOptionReadOnly, eOpenOptionWriteOnly + /// or eOpenOptionReadWrite here. /// /// \return /// OpenOptions flags for this file, or an error. @@ -404,7 +411,7 @@ public: llvm::Expected GetOptions() const override; static char ID; - virtual bool isA(const void *classID) const override { + bool isA(const void *classID) const override { return classID == &ID || File::isA(classID); } static bool classof(const File *file) { return file->isA(&ID); } @@ -428,6 +435,45 @@ private: const NativeFile &operator=(const NativeFile &) = delete; }; +class SerialPort : public NativeFile { +public: + struct Options { + std::optional BaudRate; + std::optional Parity; + std::optional ParityCheck; + std::optional StopBits; + }; + + // Obtain Options corresponding to the passed URL query string + // (i.e. the part after '?'). + static llvm::Expected OptionsFromURL(llvm::StringRef urlqs); + + static llvm::Expected> + Create(int fd, OpenOptions options, Options serial_options, + bool transfer_ownership); + + bool IsValid() const override { + return NativeFile::IsValid() && m_is_interactive == eLazyBoolYes; + } + + Status Close() override; + + static char ID; + bool isA(const void *classID) const override { + return classID == &ID || File::isA(classID); + } + static bool classof(const File *file) { return file->isA(&ID); } + +private: + SerialPort(int fd, OpenOptions options, Options serial_options, + bool transfer_ownership); + + SerialPort(const SerialPort &) = delete; + const SerialPort &operator=(const SerialPort &) = delete; + + TerminalState m_state; +}; + } // namespace lldb_private #endif // LLDB_HOST_FILE_H diff --git a/gnu/llvm/lldb/include/lldb/Host/FileSystem.h b/gnu/llvm/lldb/include/lldb/Host/FileSystem.h index 93563d4d26e..823e7710b4e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/FileSystem.h +++ b/gnu/llvm/lldb/include/lldb/Host/FileSystem.h @@ -10,19 +10,18 @@ #define LLDB_HOST_FILESYSTEM_H #include "lldb/Host/File.h" -#include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/Chrono.h" -#include "llvm/Support/FileCollector.h" #include "llvm/Support/VirtualFileSystem.h" #include "lldb/lldb-types.h" #include #include +#include #include namespace lldb_private { @@ -31,16 +30,9 @@ public: static const char *DEV_NULL; static const char *PATH_CONVERSION_ERROR; - FileSystem() - : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr), - m_home_directory() {} - FileSystem(std::shared_ptr collector) - : m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)), - m_home_directory(), m_mapped(false) {} - FileSystem(llvm::IntrusiveRefCntPtr fs, - bool mapped = false) - : m_fs(std::move(fs)), m_collector(nullptr), m_home_directory(), - m_mapped(mapped) {} + FileSystem() : m_fs(llvm::vfs::getRealFileSystem()) {} + FileSystem(llvm::IntrusiveRefCntPtr fs) + : m_fs(std::move(fs)) {} FileSystem(const FileSystem &fs) = delete; FileSystem &operator=(const FileSystem &fs) = delete; @@ -48,8 +40,6 @@ public: static FileSystem &Instance(); static void Initialize(); - static void Initialize(std::shared_ptr collector); - static llvm::Error Initialize(const FileSpec &mapping); static void Initialize(llvm::IntrusiveRefCntPtr fs); static void Terminate(); @@ -142,14 +132,28 @@ public: void Resolve(FileSpec &file_spec); /// \} + /// Remove a single file. + /// + /// The path must specify a file and not a directory. + /// \{ + Status RemoveFile(const FileSpec &file_spec); + Status RemoveFile(const llvm::Twine &path); + /// \} + //// Create memory buffer from path. /// \{ - std::shared_ptr CreateDataBuffer(const llvm::Twine &path, - uint64_t size = 0, - uint64_t offset = 0); - std::shared_ptr CreateDataBuffer(const FileSpec &file_spec, - uint64_t size = 0, - uint64_t offset = 0); + std::shared_ptr CreateDataBuffer(const llvm::Twine &path, + uint64_t size = 0, + uint64_t offset = 0); + std::shared_ptr CreateDataBuffer(const FileSpec &file_spec, + uint64_t size = 0, + uint64_t offset = 0); + std::shared_ptr + CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size = 0, + uint64_t offset = 0); + std::shared_ptr + CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size = 0, + uint64_t offset = 0); /// \} /// Call into the Host to see if it can help find the file. @@ -184,24 +188,16 @@ public: std::error_code GetRealPath(const llvm::Twine &path, llvm::SmallVectorImpl &output) const; - llvm::ErrorOr GetExternalPath(const llvm::Twine &path); - llvm::ErrorOr GetExternalPath(const FileSpec &file_spec); - llvm::IntrusiveRefCntPtr GetVirtualFileSystem() { return m_fs; } - void Collect(const FileSpec &file_spec); - void Collect(const llvm::Twine &file); - void SetHomeDirectory(std::string home_directory); private: - static llvm::Optional &InstanceImpl(); + static std::optional &InstanceImpl(); llvm::IntrusiveRefCntPtr m_fs; - std::shared_ptr m_collector; std::string m_home_directory; - bool m_mapped = false; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Host/Host.h b/gnu/llvm/lldb/include/lldb/Host/Host.h index 1fdf7eab7eb..4fc2bd128b0 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Host.h +++ b/gnu/llvm/lldb/include/lldb/Host/Host.h @@ -13,6 +13,7 @@ #include "lldb/Host/HostThread.h" #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/Timeout.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-private.h" @@ -61,54 +62,33 @@ inline bool operator!=(WaitStatus a, WaitStatus b) { return !(a == b); } /// Host is a class that answers information about the host operating system. class Host { public: - typedef std::function // Exit value of process if signal is zero + typedef std::function // Exit value of process if signal is + // zero MonitorChildProcessCallback; /// Start monitoring a child process. /// /// Allows easy monitoring of child processes. \a callback will be called - /// when the child process exits or if it gets a signal. The callback will - /// only be called with signals if \a monitor_signals is \b true. \a - /// callback will usually be called from another thread so the callback - /// function must be thread safe. - /// - /// When the callback gets called, the return value indicates if monitoring - /// should stop. If \b true is returned from \a callback the information - /// will be removed. If \b false is returned then monitoring will continue. - /// If the child process exits, the monitoring will automatically stop after - /// the callback returned regardless of the callback return value. + /// when the child process exits or if it dies from a signal. /// /// \param[in] callback /// A function callback to call when a child receives a signal - /// (if \a monitor_signals is true) or a child exits. + /// or exits. /// /// \param[in] pid - /// The process ID of a child process to monitor, -1 for all - /// processes. - /// - /// \param[in] monitor_signals - /// If \b true the callback will get called when the child - /// process gets a signal. If \b false, the callback will only - /// get called if the child process exits. + /// The process ID of a child process to monitor. /// /// \return /// A thread handle that can be used to cancel the thread that /// was spawned to monitor \a pid. - /// - /// \see static void Host::StopMonitoringChildProcess (uint32_t) static llvm::Expected StartMonitoringChildProcess(const MonitorChildProcessCallback &callback, - lldb::pid_t pid, bool monitor_signals); - - enum SystemLogType { eSystemLogWarning, eSystemLogError }; + lldb::pid_t pid); - static void SystemLog(SystemLogType type, const char *format, ...) - __attribute__((format(printf, 2, 3))); - - static void SystemLog(SystemLogType type, const char *format, va_list args); + /// Emit the given message to the operating system log. + static void SystemLog(llvm::StringRef message); /// Get the process ID for the calling process. /// @@ -259,6 +239,13 @@ public: static bool OpenFileInExternalEditor(const FileSpec &file_spec, uint32_t line_no); + /// Check if we're running in an interactive graphical session. + /// + /// \return + /// True if we're running in an interactive graphical session. False if + /// we're not or don't know. + static bool IsInteractiveGraphicSession(); + static Environment GetEnvironment(); static std::unique_ptr @@ -269,6 +256,19 @@ protected: ProcessInstanceInfoList &proc_infos); }; +/// Log handler that emits log messages to the operating system log. +class SystemLogHandler : public LogHandler { +public: + SystemLogHandler(); + void Emit(llvm::StringRef message) override; + + bool isA(const void *ClassID) const override { return ClassID == &ID; } + static bool classof(const LogHandler *obj) { return obj->isA(&ID); } + +private: + static char ID; +}; + } // namespace lldb_private namespace llvm { diff --git a/gnu/llvm/lldb/include/lldb/Host/HostInfoBase.h b/gnu/llvm/lldb/include/lldb/Host/HostInfoBase.h index eeed881101d..42f71d91f9b 100644 --- a/gnu/llvm/lldb/include/lldb/Host/HostInfoBase.h +++ b/gnu/llvm/lldb/include/lldb/Host/HostInfoBase.h @@ -19,6 +19,7 @@ #include +#include #include namespace lldb_private { @@ -64,7 +65,8 @@ public: static const ArchSpec & GetArchitecture(ArchitectureKind arch_kind = eArchKindDefault); - static llvm::Optional ParseArchitectureKind(llvm::StringRef kind); + static std::optional + ParseArchitectureKind(llvm::StringRef kind); /// Returns the directory containing the lldb shared library. Only the /// directory member of the FileSpec is filled in. @@ -108,7 +110,9 @@ public: static FileSpec GetXcodeDeveloperDirectory() { return {}; } /// Return the directory containing a specific Xcode SDK. - static llvm::StringRef GetXcodeSDKPath(XcodeSDK sdk) { return {}; } + static llvm::Expected GetXcodeSDKPath(XcodeSDK sdk) { + return ""; + } /// Return information about module \p image_name if it is loaded in /// the current process's address space. diff --git a/gnu/llvm/lldb/include/lldb/Host/HostNativeProcessBase.h b/gnu/llvm/lldb/include/lldb/Host/HostNativeProcessBase.h index 5469f8a50e2..fed29662fab 100644 --- a/gnu/llvm/lldb/include/lldb/Host/HostNativeProcessBase.h +++ b/gnu/llvm/lldb/include/lldb/Host/HostNativeProcessBase.h @@ -30,7 +30,6 @@ public: virtual ~HostNativeProcessBase() = default; virtual Status Terminate() = 0; - virtual Status GetMainModule(FileSpec &file_spec) const = 0; virtual lldb::pid_t GetProcessId() const = 0; virtual bool IsRunning() const = 0; @@ -38,8 +37,7 @@ public: lldb::process_t GetSystemHandle() const { return m_process; } virtual llvm::Expected - StartMonitoring(const Host::MonitorChildProcessCallback &callback, - bool monitor_signals) = 0; + StartMonitoring(const Host::MonitorChildProcessCallback &callback) = 0; protected: lldb::process_t m_process; diff --git a/gnu/llvm/lldb/include/lldb/Host/HostNativeThreadBase.h b/gnu/llvm/lldb/include/lldb/Host/HostNativeThreadBase.h index bfd70d74559..1c581c279e1 100644 --- a/gnu/llvm/lldb/include/lldb/Host/HostNativeThreadBase.h +++ b/gnu/llvm/lldb/include/lldb/Host/HostNativeThreadBase.h @@ -46,7 +46,7 @@ protected: ThreadCreateTrampoline(lldb::thread_arg_t arg); lldb::thread_t m_thread = LLDB_INVALID_HOST_THREAD; - lldb::thread_result_t m_result = 0; + lldb::thread_result_t m_result = 0; // NOLINT(modernize-use-nullptr) }; } diff --git a/gnu/llvm/lldb/include/lldb/Host/HostProcess.h b/gnu/llvm/lldb/include/lldb/Host/HostProcess.h index 0b7c3036422..2871b3ab16a 100644 --- a/gnu/llvm/lldb/include/lldb/Host/HostProcess.h +++ b/gnu/llvm/lldb/include/lldb/Host/HostProcess.h @@ -37,14 +37,12 @@ public: ~HostProcess(); Status Terminate(); - Status GetMainModule(FileSpec &file_spec) const; lldb::pid_t GetProcessId() const; bool IsRunning() const; llvm::Expected - StartMonitoring(const Host::MonitorChildProcessCallback &callback, - bool monitor_signals); + StartMonitoring(const Host::MonitorChildProcessCallback &callback); HostNativeProcessBase &GetNativeProcess(); const HostNativeProcessBase &GetNativeProcess() const; diff --git a/gnu/llvm/lldb/include/lldb/Host/MainLoop.h b/gnu/llvm/lldb/include/lldb/Host/MainLoop.h index 06785bbdbe2..c88b9f8920e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/MainLoop.h +++ b/gnu/llvm/lldb/include/lldb/Host/MainLoop.h @@ -9,107 +9,16 @@ #ifndef LLDB_HOST_MAINLOOP_H #define LLDB_HOST_MAINLOOP_H -#include "lldb/Host/Config.h" -#include "lldb/Host/MainLoopBase.h" -#include "llvm/ADT/DenseMap.h" -#include -#include - -#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) -#define SIGNAL_POLLING_UNSUPPORTED 1 -#endif - +#ifdef _WIN32 +#include "lldb/Host/windows/MainLoopWindows.h" namespace lldb_private { - -// Implementation of the MainLoopBase class. It can monitor file descriptors -// for readability using ppoll, kqueue, poll or WSAPoll. On Windows it only -// supports polling sockets, and will not work on generic file handles or -// pipes. On systems without kqueue or ppoll handling singnals is not -// supported. In addition to the common base, this class provides the ability -// to invoke a given handler when a signal is received. -// -// Since this class is primarily intended to be used for single-threaded -// processing, it does not attempt to perform any internal synchronisation and -// any concurrent accesses must be protected externally. However, it is -// perfectly legitimate to have more than one instance of this class running on -// separate threads, or even a single thread (with some limitations on signal -// monitoring). -// TODO: Add locking if this class is to be used in a multi-threaded context. -class MainLoop : public MainLoopBase { -private: - class SignalHandle; - -public: - typedef std::unique_ptr SignalHandleUP; - - MainLoop(); - ~MainLoop() override; - - ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, - const Callback &callback, - Status &error) override; - - // Listening for signals from multiple MainLoop instances is perfectly safe - // as long as they don't try to listen for the same signal. The callback - // function is invoked when the control returns to the Run() function, not - // when the hander is executed. This mean that you can treat the callback as - // a normal function and perform things which would not be safe in a signal - // handler. However, since the callback is not invoked synchronously, you - // cannot use this mechanism to handle SIGSEGV and the like. - SignalHandleUP RegisterSignal(int signo, const Callback &callback, - Status &error); - - Status Run() override; - - // This should only be performed from a callback. Do not attempt to terminate - // the processing from another thread. - // TODO: Add synchronization if we want to be terminated from another thread. - void RequestTermination() override { m_terminate_request = true; } - -protected: - void UnregisterReadObject(IOObject::WaitableHandle handle) override; - - void UnregisterSignal(int signo, std::list::iterator callback_it); - -private: - void ProcessReadObject(IOObject::WaitableHandle handle); - void ProcessSignal(int signo); - - class SignalHandle { - public: - ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } - - private: - SignalHandle(MainLoop &mainloop, int signo, - std::list::iterator callback_it) - : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {} - - MainLoop &m_mainloop; - int m_signo; - std::list::iterator m_callback_it; - - friend class MainLoop; - SignalHandle(const SignalHandle &) = delete; - const SignalHandle &operator=(const SignalHandle &) = delete; - }; - - struct SignalInfo { - std::list callbacks; -#if HAVE_SIGACTION - struct sigaction old_action; -#endif - bool was_blocked : 1; - }; - class RunImpl; - - llvm::DenseMap m_read_fds; - llvm::DenseMap m_signals; -#if HAVE_SYS_EVENT_H - int m_kqueue; +using MainLoop = MainLoopWindows; +} +#else +#include "lldb/Host/posix/MainLoopPosix.h" +namespace lldb_private { +using MainLoop = MainLoopPosix; +} #endif - bool m_terminate_request : 1; -}; - -} // namespace lldb_private #endif // LLDB_HOST_MAINLOOP_H diff --git a/gnu/llvm/lldb/include/lldb/Host/MainLoopBase.h b/gnu/llvm/lldb/include/lldb/Host/MainLoopBase.h index 67857b26ac7..7365ee7a65e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/MainLoopBase.h +++ b/gnu/llvm/lldb/include/lldb/Host/MainLoopBase.h @@ -11,8 +11,10 @@ #include "lldb/Utility/IOObject.h" #include "lldb/Utility/Status.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/ErrorHandling.h" #include +#include namespace lldb_private { @@ -26,14 +28,17 @@ namespace lldb_private { // of the monitoring. When this handle is destroyed, the callback is // deregistered. // -// This class simply defines the interface common for all platforms, actual -// implementations are platform-specific. +// Since this class is primarily intended to be used for single-threaded +// processing, it does not attempt to perform any internal synchronisation and +// any concurrent accesses must be protected externally. However, it is +// perfectly legitimate to have more than one instance of this class running on +// separate threads, or even a single thread. class MainLoopBase { private: class ReadHandle; public: - MainLoopBase() = default; + MainLoopBase() : m_terminate_request(false) {} virtual ~MainLoopBase() = default; typedef std::unique_ptr ReadHandleUP; @@ -42,25 +47,37 @@ public: virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, - Status &error) { - llvm_unreachable("Not implemented"); - } + Status &error) = 0; + + // Add a pending callback that will be executed once after all the pending + // events are processed. The callback will be executed even if termination + // was requested. + void AddPendingCallback(const Callback &callback); // Waits for registered events and invoke the proper callbacks. Returns when // all callbacks deregister themselves or when someone requests termination. virtual Status Run() { llvm_unreachable("Not implemented"); } - // Requests the exit of the Run() function. - virtual void RequestTermination() { llvm_unreachable("Not implemented"); } + // This should only be performed from a callback. Do not attempt to terminate + // the processing from another thread. + virtual void RequestTermination() { m_terminate_request = true; } protected: ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) { return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle())); } - virtual void UnregisterReadObject(IOObject::WaitableHandle handle) { - llvm_unreachable("Not implemented"); - } + virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0; + + // Interrupt the loop that is currently waiting for events and execute + // the current pending callbacks immediately. + virtual void TriggerPendingCallbacks() = 0; + + void ProcessPendingCallbacks(); + + std::mutex m_callback_mutex; + std::vector m_pending_callbacks; + bool m_terminate_request : 1; private: class ReadHandle { diff --git a/gnu/llvm/lldb/include/lldb/Host/ProcessLaunchInfo.h b/gnu/llvm/lldb/include/lldb/Host/ProcessLaunchInfo.h index 3ed21637de7..8f8f9333fd1 100644 --- a/gnu/llvm/lldb/include/lldb/Host/ProcessLaunchInfo.h +++ b/gnu/llvm/lldb/include/lldb/Host/ProcessLaunchInfo.h @@ -99,21 +99,18 @@ public: bool first_arg_is_full_shell_command, uint32_t num_resumes); - void - SetMonitorProcessCallback(const Host::MonitorChildProcessCallback &callback, - bool monitor_signals); + void SetMonitorProcessCallback(Host::MonitorChildProcessCallback callback) { + m_monitor_callback = std::move(callback); + } - Host::MonitorChildProcessCallback GetMonitorProcessCallback() const { + const Host::MonitorChildProcessCallback &GetMonitorProcessCallback() const { return m_monitor_callback; } /// A Monitor callback which does not take any action on process events. Use /// this if you don't need to take any particular action when the process /// terminates, but you still need to reap it. - static bool NoOpMonitorCallback(lldb::pid_t pid, bool exited, int signal, - int status); - - bool GetMonitorSignals() const { return m_monitor_signals; } + static void NoOpMonitorCallback(lldb::pid_t pid, int signal, int status); // If the LaunchInfo has a monitor callback, then arrange to monitor the // process. Return true if the LaunchInfo has taken care of monitoring the @@ -178,8 +175,6 @@ protected: std::shared_ptr m_pty; uint32_t m_resume_count = 0; // How many times do we resume after launching Host::MonitorChildProcessCallback m_monitor_callback; - void *m_monitor_callback_baton = nullptr; - bool m_monitor_signals = false; std::string m_event_data; // A string passed to the plugin launch, having no // meaning to the upper levels of lldb. lldb::ListenerSP m_listener_sp; diff --git a/gnu/llvm/lldb/include/lldb/Host/Socket.h b/gnu/llvm/lldb/include/lldb/Host/Socket.h index 36db0ec63e9..01f790ee11f 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Socket.h +++ b/gnu/llvm/lldb/include/lldb/Host/Socket.h @@ -16,7 +16,6 @@ #include "lldb/Host/SocketAddress.h" #include "lldb/Utility/IOObject.h" -#include "lldb/Utility/Predicate.h" #include "lldb/Utility/Status.h" #ifdef _WIN32 @@ -48,6 +47,15 @@ public: ProtocolUnixAbstract }; + struct HostAndPort { + std::string hostname; + uint16_t port; + + bool operator==(const HostAndPort &R) const { + return port == R.port && hostname == R.hostname; + } + }; + static const NativeSocket kInvalidSocketValue; ~Socket() override; @@ -68,7 +76,7 @@ public: // the socket after it is initialized, but before entering a blocking accept. static llvm::Expected> TcpListen(llvm::StringRef host_and_port, bool child_processes_inherit, - Predicate *predicate, int backlog = 5); + int backlog = 5); static llvm::Expected> TcpConnect(llvm::StringRef host_and_port, bool child_processes_inherit); @@ -76,18 +84,6 @@ public: static llvm::Expected> UdpConnect(llvm::StringRef host_and_port, bool child_processes_inherit); - static Status UnixDomainConnect(llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket); - static Status UnixDomainAccept(llvm::StringRef host_and_port, - bool child_processes_inherit, Socket *&socket); - static Status UnixAbstractConnect(llvm::StringRef host_and_port, - bool child_processes_inherit, - Socket *&socket); - static Status 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); @@ -103,9 +99,8 @@ public: bool IsValid() const override { return m_socket != kInvalidSocketValue; } WaitableHandle GetWaitableHandle() override; - static bool DecodeHostAndPort(llvm::StringRef host_and_port, - std::string &host_str, std::string &port_str, - int32_t &port, Status *error_ptr); + static llvm::Expected + DecodeHostAndPort(llvm::StringRef host_and_port); // If this Socket is connected then return the URI used to connect. virtual std::string GetRemoteConnectionURI() const { return ""; }; @@ -130,6 +125,9 @@ protected: bool m_should_close_fd; }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const Socket::HostAndPort &HP); + } // namespace lldb_private #endif // LLDB_HOST_SOCKET_H diff --git a/gnu/llvm/lldb/include/lldb/Host/Terminal.h b/gnu/llvm/lldb/include/lldb/Host/Terminal.h index ca91d6b5972..8ff6d75657a 100644 --- a/gnu/llvm/lldb/include/lldb/Host/Terminal.h +++ b/gnu/llvm/lldb/include/lldb/Host/Terminal.h @@ -10,15 +10,35 @@ #define LLDB_HOST_TERMINAL_H #if defined(__cplusplus) -#include "lldb/Host/Config.h" #include "lldb/lldb-private.h" - -struct termios; +#include "llvm/Support/Error.h" namespace lldb_private { +class TerminalState; + class Terminal { public: + enum class Parity { + No, + Even, + Odd, + Space, + Mark, + }; + + enum class ParityCheck { + // No parity checking + No, + // Replace erraneous bytes with NUL + ReplaceWithNUL, + // Ignore erraneous bytes + Ignore, + // Mark erraneous bytes by prepending them with \xFF\x00; real \xFF + // is escaped to \xFF\xFF + Mark, + }; + Terminal(int fd = -1) : m_fd(fd) {} ~Terminal() = default; @@ -33,25 +53,54 @@ public: void Clear() { m_fd = -1; } - bool SetEcho(bool enabled); + llvm::Error SetEcho(bool enabled); + + llvm::Error SetCanonical(bool enabled); + + llvm::Error SetRaw(); - bool SetCanonical(bool enabled); + llvm::Error SetBaudRate(unsigned int baud_rate); + + llvm::Error SetStopBits(unsigned int stop_bits); + + llvm::Error SetParity(Parity parity); + + llvm::Error SetParityCheck(ParityCheck parity_check); + + llvm::Error SetHardwareFlowControl(bool enabled); protected: + struct Data; + int m_fd; // This may or may not be a terminal file descriptor + + llvm::Expected GetData(); + llvm::Error SetData(const Data &data); + + friend class TerminalState; }; -/// \class State Terminal.h "lldb/Host/Terminal.h" -/// A terminal state saving/restoring class. +/// \class TerminalState Terminal.h "lldb/Host/Terminal.h" +/// A RAII-friendly terminal state saving/restoring class. /// /// This class can be used to remember the terminal state for a file /// descriptor and later restore that state as it originally was. class TerminalState { public: - /// Default constructor - TerminalState(); + /// Construct a new instance and optionally save terminal state. + /// + /// \param[in] term + /// The Terminal instance holding the file descriptor to save the state + /// of. If the instance is not associated with a fd, no state will + /// be saved. + /// + /// \param[in] save_process_group + /// If \b true, save the process group settings, else do not + /// save the process group settings for a TTY. + TerminalState(Terminal term = -1, bool save_process_group = false); - /// Destructor + /// Destroy the instance, restoring terminal state if saved. If restoring + /// state is undesirable, the instance needs to be reset before destruction. ~TerminalState(); /// Save the TTY state for \a fd. @@ -60,8 +109,8 @@ public: /// "save_process_group" is true, attempt to save the process group info for /// the TTY. /// - /// \param[in] fd - /// The file descriptor to save the state of. + /// \param[in] term + /// The Terminal instance holding fd to save. /// /// \param[in] save_process_group /// If \b true, save the process group settings, else do not @@ -70,7 +119,7 @@ public: /// \return /// Returns \b true if \a fd describes a TTY and if the state /// was able to be saved, \b false otherwise. - bool Save(int fd, bool save_process_group); + bool Save(Terminal term, bool save_process_group); /// Restore the TTY state to the cached state. /// @@ -115,66 +164,10 @@ protected: bool ProcessGroupIsValid() const; // Member variables - Terminal m_tty; ///< A terminal - int m_tflags = -1; ///< Cached tflags information. -#if LLDB_ENABLE_TERMIOS - std::unique_ptr - m_termios_up; ///< Cached terminal state information. -#endif - lldb::pid_t m_process_group = -1; ///< Cached process group information. -}; - -/// \class TerminalStateSwitcher Terminal.h "lldb/Host/Terminal.h" -/// A TTY state switching class. -/// -/// This class can be used to remember 2 TTY states for a given file -/// descriptor and switch between the two states. -class TerminalStateSwitcher { -public: - /// Constructor - TerminalStateSwitcher(); - - /// Destructor - ~TerminalStateSwitcher(); - - /// Get the number of possible states to save. - /// - /// \return - /// The number of states that this TTY switcher object contains. - uint32_t GetNumberOfStates() const; - - /// Restore the TTY state for state at index \a idx. - /// - /// \return - /// Returns \b true if the TTY state was successfully restored, - /// \b false otherwise. - bool Restore(uint32_t idx) const; - - /// Save the TTY state information for the state at index \a idx. The TTY - /// state is saved for the file descriptor \a fd and the process group - /// information will also be saved if requested by \a save_process_group. - /// - /// \param[in] idx - /// The index into the state array where the state should be - /// saved. - /// - /// \param[in] fd - /// The file descriptor for which to save the settings. - /// - /// \param[in] save_process_group - /// If \b true, save the process group information for the TTY. - /// - /// \return - /// Returns \b true if the save was successful, \b false - /// otherwise. - bool Save(uint32_t idx, int fd, bool save_process_group); - -protected: - // Member variables - mutable uint32_t m_currentState = - UINT32_MAX; ///< The currently active TTY state index. - TerminalState - m_ttystates[2]; ///< The array of TTY states that holds saved TTY info. + Terminal m_tty; ///< A terminal + int m_tflags = -1; ///< Cached tflags information. + std::unique_ptr m_data; ///< Platform-specific implementation. + lldb::pid_t m_process_group = -1; ///< Cached process group information. }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Host/ThreadLauncher.h b/gnu/llvm/lldb/include/lldb/Host/ThreadLauncher.h index 00b42fa6a11..8bb6c79466a 100644 --- a/gnu/llvm/lldb/include/lldb/Host/ThreadLauncher.h +++ b/gnu/llvm/lldb/include/lldb/Host/ThreadLauncher.h @@ -20,8 +20,8 @@ namespace lldb_private { class ThreadLauncher { public: static llvm::Expected - LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, - lldb::thread_arg_t thread_arg, + LaunchThread(llvm::StringRef name, + std::function thread_function, size_t min_stack_byte_size = 0); // Minimum stack size in bytes, // set stack size to zero for // default platform thread stack @@ -29,12 +29,11 @@ public: struct HostThreadCreateInfo { std::string thread_name; - lldb::thread_func_t thread_fptr; - lldb::thread_arg_t thread_arg; + std::function impl; - HostThreadCreateInfo(const char *name, lldb::thread_func_t fptr, - lldb::thread_arg_t arg) - : thread_name(name ? name : ""), thread_fptr(fptr), thread_arg(arg) {} + HostThreadCreateInfo(std::string thread_name, + std::function impl) + : thread_name(std::move(thread_name)), impl(std::move(impl)) {} }; }; } diff --git a/gnu/llvm/lldb/include/lldb/Host/XML.h b/gnu/llvm/lldb/include/lldb/Host/XML.h index 9edf46bf09d..da0f9cd7aa8 100644 --- a/gnu/llvm/lldb/include/lldb/Host/XML.h +++ b/gnu/llvm/lldb/include/lldb/Host/XML.h @@ -76,8 +76,8 @@ public: XMLNode GetChild() const; - llvm::StringRef GetAttributeValue(const char *name, - const char *fail_value = nullptr) const; + std::string GetAttributeValue(const char *name, + const char *fail_value = nullptr) const; bool GetAttributeValueAsUnsigned(const char *name, uint64_t &value, uint64_t fail_value = 0, int base = 0) const; diff --git a/gnu/llvm/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/gnu/llvm/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 770149e3fb2..057c07b1536 100644 --- a/gnu/llvm/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/gnu/llvm/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -15,6 +15,7 @@ #include "lldb/Host/Host.h" #include "lldb/Host/MainLoop.h" #include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Iterable.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/TraceGDBRemotePackets.h" #include "lldb/Utility/UnimplementedError.h" @@ -26,6 +27,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include +#include #include #include @@ -48,6 +50,16 @@ class NativeProcessProtocol { public: virtual ~NativeProcessProtocol() = default; + typedef std::vector> thread_collection; + template + static NativeThreadProtocol &thread_list_adapter(I &iter) { + assert(*iter); + return **iter; + } + typedef LockingAdaptedIterable + ThreadIterable; + virtual Status Resume(const ResumeActionList &resume_actions) = 0; virtual Status Halt() = 0; @@ -160,7 +172,7 @@ public: // Watchpoint functions virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const; - virtual llvm::Optional> + virtual std::optional> GetHardwareDebugSupportInfo() const; virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, @@ -193,7 +205,7 @@ public: GetAuxvData() const = 0; // Exit Status - virtual llvm::Optional GetExitStatus(); + virtual std::optional GetExitStatus(); virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange); @@ -204,12 +216,16 @@ public: void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; } - lldb::tid_t GetCurrentThreadID() { return m_current_thread_id; } + lldb::tid_t GetCurrentThreadID() const { return m_current_thread_id; } NativeThreadProtocol *GetCurrentThread() { return GetThreadByID(m_current_thread_id); } + ThreadIterable Threads() const { + return ThreadIterable(m_threads, m_threads_mutex); + } + // Access to inferior stdio virtual int GetTerminalFileDescriptor() { return m_terminal_fd; } @@ -250,8 +266,10 @@ public: auxv = (1u << 4), libraries_svr4 = (1u << 5), memory_tagging = (1u << 6), + savecore = (1u << 7), + siginfo_read = (1u << 8), - LLVM_MARK_AS_BITMASK_ENUM(memory_tagging) + LLVM_MARK_AS_BITMASK_ENUM(siginfo_read) }; class Factory { @@ -308,6 +326,12 @@ public: virtual Extension GetSupportedExtensions() const { return {}; } }; + /// Notify tracers that the target process will resume + virtual void NotifyTracersProcessWillResume() {} + + /// Notify tracers that the target process just stopped + virtual void NotifyTracersProcessDidStop() {} + /// Start tracing a process or its threads. /// /// \param[in] json_params @@ -369,6 +393,19 @@ public: m_enabled_extensions = flags; } + /// Write a core dump (without crashing the program). + /// + /// \param[in] path_hint + /// Suggested core dump path (optional, can be empty). + /// + /// \return + /// Path to the core dump if successfully written, an error + /// otherwise. + virtual llvm::Expected SaveCore(llvm::StringRef path_hint) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Not implemented"); + } + protected: struct SoftwareBreakpoint { uint32_t ref_count; @@ -386,7 +423,7 @@ protected: lldb::StateType m_state = lldb::eStateInvalid; mutable std::recursive_mutex m_state_mutex; - llvm::Optional m_exit_status; + std::optional m_exit_status; NativeDelegate &m_delegate; NativeWatchpointList m_watchpoint_list; @@ -442,7 +479,7 @@ protected: /// /// Provide a mechanism for a delegate to clear out any exec- /// sensitive data. - void NotifyDidExec(); + virtual void NotifyDidExec(); NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid); diff --git a/gnu/llvm/lldb/include/lldb/Host/common/NativeRegisterContext.h b/gnu/llvm/lldb/include/lldb/Host/common/NativeRegisterContext.h index f7568fe31b8..0a7647d7808 100644 --- a/gnu/llvm/lldb/include/lldb/Host/common/NativeRegisterContext.h +++ b/gnu/llvm/lldb/include/lldb/Host/common/NativeRegisterContext.h @@ -51,7 +51,7 @@ public: virtual Status WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) = 0; - virtual Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) = 0; + virtual Status ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) = 0; virtual Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) = 0; diff --git a/gnu/llvm/lldb/include/lldb/Host/common/NativeThreadProtocol.h b/gnu/llvm/lldb/include/lldb/Host/common/NativeThreadProtocol.h index 5cf26bd9593..35ccc48d62d 100644 --- a/gnu/llvm/lldb/include/lldb/Host/common/NativeThreadProtocol.h +++ b/gnu/llvm/lldb/include/lldb/Host/common/NativeThreadProtocol.h @@ -12,9 +12,13 @@ #include #include "lldb/Host/Debug.h" +#include "lldb/Utility/UnimplementedError.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" + namespace lldb_private { // NativeThreadProtocol class NativeThreadProtocol { @@ -47,6 +51,11 @@ public: virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr) = 0; + virtual llvm::Expected> + GetSiginfo() const { + return llvm::make_error(); + } + protected: NativeProcessProtocol &m_process; lldb::tid_t m_tid; diff --git a/gnu/llvm/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h b/gnu/llvm/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h index 56f20bbd23d..d265b8acf5a 100644 --- a/gnu/llvm/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h +++ b/gnu/llvm/lldb/include/lldb/Host/freebsd/HostInfoFreeBSD.h @@ -12,14 +12,14 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include namespace lldb_private { class HostInfoFreeBSD : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); - static bool GetOSBuildString(std::string &s); - static bool GetOSKernelDescription(std::string &s); + static std::optional GetOSBuildString(); static FileSpec GetProgramFileSpec(); }; } diff --git a/gnu/llvm/lldb/include/lldb/Host/linux/Host.h b/gnu/llvm/lldb/include/lldb/Host/linux/Host.h index 409a9fc9b32..ef1e74cd1d5 100644 --- a/gnu/llvm/lldb/include/lldb/Host/linux/Host.h +++ b/gnu/llvm/lldb/include/lldb/Host/linux/Host.h @@ -10,12 +10,12 @@ #define LLDB_HOST_LINUX_HOST_H #include "lldb/lldb-types.h" -#include "llvm/ADT/Optional.h" +#include namespace lldb_private { // Get PID (i.e. the primary thread ID) corresponding to the specified TID. -llvm::Optional getPIDForTID(lldb::pid_t tid); +std::optional getPIDForTID(lldb::pid_t tid); } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Host/linux/HostInfoLinux.h b/gnu/llvm/lldb/include/lldb/Host/linux/HostInfoLinux.h index 32200464886..2964f3f1dc9 100644 --- a/gnu/llvm/lldb/include/lldb/Host/linux/HostInfoLinux.h +++ b/gnu/llvm/lldb/include/lldb/Host/linux/HostInfoLinux.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/VersionTuple.h" +#include #include namespace lldb_private { @@ -26,8 +27,7 @@ public: static void Terminate(); static llvm::VersionTuple GetOSVersion(); - static bool GetOSBuildString(std::string &s); - static bool GetOSKernelDescription(std::string &s); + static std::optional GetOSBuildString(); static llvm::StringRef GetDistributionId(); static FileSpec GetProgramFileSpec(); diff --git a/gnu/llvm/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/gnu/llvm/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h index 4623932ab2b..0402509cfa2 100644 --- a/gnu/llvm/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h +++ b/gnu/llvm/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h @@ -13,6 +13,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/XcodeSDK.h" #include "llvm/Support/VersionTuple.h" +#include namespace lldb_private { @@ -24,14 +25,13 @@ class HostInfoMacOSX : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); static llvm::VersionTuple GetMacCatalystVersion(); - static bool GetOSBuildString(std::string &s); - static bool GetOSKernelDescription(std::string &s); + static std::optional GetOSBuildString(); static FileSpec GetProgramFileSpec(); static FileSpec GetXcodeContentsDirectory(); static FileSpec GetXcodeDeveloperDirectory(); /// Query xcrun to find an Xcode SDK directory. - static llvm::StringRef GetXcodeSDKPath(XcodeSDK sdk); + static llvm::Expected GetXcodeSDKPath(XcodeSDK sdk); /// Shared cache utilities static SharedCacheImageInfo diff --git a/gnu/llvm/lldb/include/lldb/Host/macosx/HostThreadMacOSX.h b/gnu/llvm/lldb/include/lldb/Host/macosx/HostThreadMacOSX.h index 4e41119d97c..0299be38740 100644 --- a/gnu/llvm/lldb/include/lldb/Host/macosx/HostThreadMacOSX.h +++ b/gnu/llvm/lldb/include/lldb/Host/macosx/HostThreadMacOSX.h @@ -17,8 +17,7 @@ class HostThreadMacOSX : public HostThreadPosix { friend class ThreadLauncher; public: - HostThreadMacOSX(); - HostThreadMacOSX(lldb::thread_t thread); + using HostThreadPosix::HostThreadPosix; protected: static lldb::thread_result_t ThreadCreateTrampoline(lldb::thread_arg_t arg); diff --git a/gnu/llvm/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h b/gnu/llvm/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h index f9ad66eb2b2..01daefaedba 100644 --- a/gnu/llvm/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h +++ b/gnu/llvm/lldb/include/lldb/Host/netbsd/HostInfoNetBSD.h @@ -12,14 +12,14 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include namespace lldb_private { class HostInfoNetBSD : public HostInfoPosix { public: static llvm::VersionTuple GetOSVersion(); - static bool GetOSBuildString(std::string &s); - static bool GetOSKernelDescription(std::string &s); + static std::optional GetOSBuildString(); static FileSpec GetProgramFileSpec(); }; } diff --git a/gnu/llvm/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/gnu/llvm/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h index 42be989dfa7..35773d5907e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h +++ b/gnu/llvm/lldb/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h @@ -16,9 +16,9 @@ #include "lldb/lldb-forward.h" #include "lldb/Host/Pipe.h" +#include "lldb/Host/Socket.h" #include "lldb/Utility/Connection.h" #include "lldb/Utility/IOObject.h" -#include "lldb/Utility/Predicate.h" namespace lldb_private { @@ -28,16 +28,8 @@ 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; + typedef llvm::function_ref + socket_id_callback_type; ConnectionFileDescriptor(bool child_processes_inherit = false); @@ -49,7 +41,12 @@ public: bool IsConnected() const override; - lldb::ConnectionStatus Connect(llvm::StringRef s, Status *error_ptr) override; + lldb::ConnectionStatus Connect(llvm::StringRef url, + Status *error_ptr) override; + + lldb::ConnectionStatus Connect(llvm::StringRef url, + socket_id_callback_type socket_id_callback, + Status *error_ptr); lldb::ConnectionStatus Disconnect(Status *error_ptr) override; @@ -66,9 +63,7 @@ public: bool InterruptRead() override; - lldb::IOObjectSP GetReadObject() override { return m_read_sp; } - - uint16_t GetListeningPort(const Timeout &timeout); + lldb::IOObjectSP GetReadObject() override { return m_io_sp; } bool GetChildProcessesInherit() const; void SetChildProcessesInherit(bool child_processes_inherit); @@ -78,37 +73,68 @@ protected: void CloseCommandPipe(); - lldb::ConnectionStatus SocketListenAndAccept(llvm::StringRef host_and_port, - Status *error_ptr); + lldb::ConnectionStatus + AcceptSocket(Socket::SocketProtocol socket_protocol, + llvm::StringRef socket_name, + llvm::function_ref post_listen_callback, + Status *error_ptr); + + lldb::ConnectionStatus ConnectSocket(Socket::SocketProtocol socket_protocol, + llvm::StringRef socket_name, + Status *error_ptr); + + lldb::ConnectionStatus AcceptTCP(llvm::StringRef host_and_port, + socket_id_callback_type socket_id_callback, + Status *error_ptr); lldb::ConnectionStatus ConnectTCP(llvm::StringRef host_and_port, + socket_id_callback_type socket_id_callback, Status *error_ptr); - lldb::ConnectionStatus ConnectUDP(llvm::StringRef args, Status *error_ptr); + lldb::ConnectionStatus ConnectUDP(llvm::StringRef args, + socket_id_callback_type socket_id_callback, + Status *error_ptr); + + lldb::ConnectionStatus + ConnectNamedSocket(llvm::StringRef socket_name, + socket_id_callback_type socket_id_callback, + Status *error_ptr); + + lldb::ConnectionStatus + AcceptNamedSocket(llvm::StringRef socket_name, + socket_id_callback_type socket_id_callback, + Status *error_ptr); + + lldb::ConnectionStatus + AcceptAbstractSocket(llvm::StringRef socket_name, + socket_id_callback_type socket_id_callback, + Status *error_ptr); - lldb::ConnectionStatus NamedSocketConnect(llvm::StringRef socket_name, - Status *error_ptr); + lldb::ConnectionStatus + ConnectAbstractSocket(llvm::StringRef socket_name, + socket_id_callback_type socket_id_callback, + Status *error_ptr); - lldb::ConnectionStatus NamedSocketAccept(llvm::StringRef socket_name, - Status *error_ptr); + lldb::ConnectionStatus ConnectFD(llvm::StringRef args, + socket_id_callback_type socket_id_callback, + Status *error_ptr); - lldb::ConnectionStatus UnixAbstractSocketConnect(llvm::StringRef socket_name, - Status *error_ptr); + lldb::ConnectionStatus ConnectFile(llvm::StringRef args, + socket_id_callback_type socket_id_callback, + Status *error_ptr); - lldb::IOObjectSP m_read_sp; - lldb::IOObjectSP m_write_sp; + lldb::ConnectionStatus + ConnectSerialPort(llvm::StringRef args, + socket_id_callback_type socket_id_callback, + Status *error_ptr); - Predicate - m_port_predicate; // Used when binding to port zero to wait for the thread - // that creates the socket, binds and listens to - // resolve the port number. + lldb::IOObjectSP m_io_sp; Pipe m_pipe; std::recursive_mutex m_mutex; std::atomic m_shutting_down; // This marks that we are shutting down so // if we get woken up from // BytesAvailable to disconnect, we won't try to read again. - bool m_waiting_for_accept = false; bool m_child_processes_inherit; std::string m_uri; diff --git a/gnu/llvm/lldb/include/lldb/Host/posix/HostInfoPosix.h b/gnu/llvm/lldb/include/lldb/Host/posix/HostInfoPosix.h index 825c79f53ec..8d070d3ac1e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/posix/HostInfoPosix.h +++ b/gnu/llvm/lldb/include/lldb/Host/posix/HostInfoPosix.h @@ -11,6 +11,7 @@ #include "lldb/Host/HostInfoBase.h" #include "lldb/Utility/FileSpec.h" +#include namespace lldb_private { @@ -22,6 +23,7 @@ class HostInfoPosix : public HostInfoBase { public: static size_t GetPageSize(); static bool GetHostname(std::string &s); + static std::optional GetOSKernelDescription(); static uint32_t GetUserID(); static uint32_t GetGroupID(); diff --git a/gnu/llvm/lldb/include/lldb/Host/posix/HostProcessPosix.h b/gnu/llvm/lldb/include/lldb/Host/posix/HostProcessPosix.h index 5def1b77eef..6d3d8d94a87 100644 --- a/gnu/llvm/lldb/include/lldb/Host/posix/HostProcessPosix.h +++ b/gnu/llvm/lldb/include/lldb/Host/posix/HostProcessPosix.h @@ -27,14 +27,12 @@ public: static Status Signal(lldb::process_t process, int signo); Status Terminate() override; - Status GetMainModule(FileSpec &file_spec) const override; lldb::pid_t GetProcessId() const override; bool IsRunning() const override; llvm::Expected - StartMonitoring(const Host::MonitorChildProcessCallback &callback, - bool monitor_signals) override; + StartMonitoring(const Host::MonitorChildProcessCallback &callback) override; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Host/posix/MainLoopPosix.h b/gnu/llvm/lldb/include/lldb/Host/posix/MainLoopPosix.h new file mode 100644 index 00000000000..07497b7b8c2 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Host/posix/MainLoopPosix.h @@ -0,0 +1,99 @@ +//===-- MainLoopPosix.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_POSIX_MAINLOOPPOSIX_H +#define LLDB_HOST_POSIX_MAINLOOPPOSIX_H + +#include "lldb/Host/Config.h" +#include "lldb/Host/MainLoopBase.h" +#include "lldb/Host/Pipe.h" +#include "llvm/ADT/DenseMap.h" +#include +#include +#include +#include + +namespace lldb_private { + +// Implementation of the MainLoopBase class. It can monitor file descriptors for +// readability using ppoll, kqueue, or pselect. In addition to the common base, +// this class provides the ability to invoke a given handler when a signal is +// received. +class MainLoopPosix : public MainLoopBase { +private: + class SignalHandle; + +public: + typedef std::unique_ptr SignalHandleUP; + + MainLoopPosix(); + ~MainLoopPosix() override; + + ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, + const Callback &callback, + Status &error) override; + + // Listening for signals from multiple MainLoop instances is perfectly safe + // as long as they don't try to listen for the same signal. The callback + // function is invoked when the control returns to the Run() function, not + // when the hander is executed. This mean that you can treat the callback as + // a normal function and perform things which would not be safe in a signal + // handler. However, since the callback is not invoked synchronously, you + // cannot use this mechanism to handle SIGSEGV and the like. + SignalHandleUP RegisterSignal(int signo, const Callback &callback, + Status &error); + + Status Run() override; + +protected: + void UnregisterReadObject(IOObject::WaitableHandle handle) override; + void UnregisterSignal(int signo, std::list::iterator callback_it); + + void TriggerPendingCallbacks() override; + +private: + void ProcessReadObject(IOObject::WaitableHandle handle); + void ProcessSignal(int signo); + + class SignalHandle { + public: + ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); } + + private: + SignalHandle(MainLoopPosix &mainloop, int signo, + std::list::iterator callback_it) + : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {} + + MainLoopPosix &m_mainloop; + int m_signo; + std::list::iterator m_callback_it; + + friend class MainLoopPosix; + SignalHandle(const SignalHandle &) = delete; + const SignalHandle &operator=(const SignalHandle &) = delete; + }; + + struct SignalInfo { + std::list callbacks; + struct sigaction old_action; + bool was_blocked : 1; + }; + class RunImpl; + + llvm::DenseMap m_read_fds; + llvm::DenseMap m_signals; + Pipe m_trigger_pipe; + std::atomic m_triggering; +#if HAVE_SYS_EVENT_H + int m_kqueue; +#endif +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_POSIX_MAINLOOPPOSIX_H diff --git a/gnu/llvm/lldb/include/lldb/Host/windows/HostInfoWindows.h b/gnu/llvm/lldb/include/lldb/Host/windows/HostInfoWindows.h index f01113e9004..8a4f5c7cb84 100644 --- a/gnu/llvm/lldb/include/lldb/Host/windows/HostInfoWindows.h +++ b/gnu/llvm/lldb/include/lldb/Host/windows/HostInfoWindows.h @@ -12,6 +12,7 @@ #include "lldb/Host/HostInfoBase.h" #include "lldb/Utility/FileSpec.h" #include "llvm/Support/VersionTuple.h" +#include namespace lldb_private { class UserIDResolver; @@ -27,8 +28,8 @@ public: static UserIDResolver &GetUserIDResolver(); static llvm::VersionTuple GetOSVersion(); - static bool GetOSBuildString(std::string &s); - static bool GetOSKernelDescription(std::string &s); + static std::optional GetOSBuildString(); + static std::optional GetOSKernelDescription(); static bool GetHostname(std::string &s); static FileSpec GetProgramFileSpec(); static FileSpec GetDefaultShell(); diff --git a/gnu/llvm/lldb/include/lldb/Host/windows/HostProcessWindows.h b/gnu/llvm/lldb/include/lldb/Host/windows/HostProcessWindows.h index 925d565c275..5b6e8b1c99e 100644 --- a/gnu/llvm/lldb/include/lldb/Host/windows/HostProcessWindows.h +++ b/gnu/llvm/lldb/include/lldb/Host/windows/HostProcessWindows.h @@ -25,18 +25,14 @@ public: void SetOwnsHandle(bool owns); Status Terminate() override; - Status GetMainModule(FileSpec &file_spec) const override; lldb::pid_t GetProcessId() const override; bool IsRunning() const override; virtual llvm::Expected - StartMonitoring(const Host::MonitorChildProcessCallback &callback, - bool monitor_signals) override; + StartMonitoring(const Host::MonitorChildProcessCallback &callback) override; private: - static lldb::thread_result_t MonitorThread(void *thread_arg); - void Close(); bool m_owns_handle; diff --git a/gnu/llvm/lldb/include/lldb/Host/windows/MainLoopWindows.h b/gnu/llvm/lldb/include/lldb/Host/windows/MainLoopWindows.h new file mode 100644 index 00000000000..33e179e6c12 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Host/windows/MainLoopWindows.h @@ -0,0 +1,53 @@ +//===-- MainLoopWindows.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_WINDOWS_MAINLOOPWINDOWS_H +#define LLDB_HOST_WINDOWS_MAINLOOPWINDOWS_H + +#include "lldb/Host/Config.h" +#include "lldb/Host/MainLoopBase.h" +#include +#include +#include + +namespace lldb_private { + +// Windows-specific implementation of the MainLoopBase class. It can monitor +// socket descriptors for readability using WSAEventSelect. Non-socket file +// descriptors are not supported. +class MainLoopWindows : public MainLoopBase { +public: + MainLoopWindows(); + ~MainLoopWindows() override; + + ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, + const Callback &callback, + Status &error) override; + + Status Run() override; + +protected: + void UnregisterReadObject(IOObject::WaitableHandle handle) override; + + void TriggerPendingCallbacks() override; + +private: + void ProcessReadObject(IOObject::WaitableHandle handle); + llvm::Expected Poll(); + + struct FdInfo { + void *event; + Callback callback; + }; + llvm::DenseMap m_read_fds; + void *m_trigger_event; +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_WINDOWS_MAINLOOPWINDOWS_H diff --git a/gnu/llvm/lldb/include/lldb/Host/windows/PosixApi.h b/gnu/llvm/lldb/include/lldb/Host/windows/PosixApi.h index 26398ac5eb1..981261a3ea3 100644 --- a/gnu/llvm/lldb/include/lldb/Host/windows/PosixApi.h +++ b/gnu/llvm/lldb/include/lldb/Host/windows/PosixApi.h @@ -56,14 +56,12 @@ #define S_IRWXO 0 #endif -#if HAVE_SYS_TYPES_H // pyconfig.h typedefs this. We require python headers to be included before // any LLDB headers, but there's no way to prevent python's pid_t definition // from leaking, so this is the best option. #ifndef NO_PID_T #include #endif -#endif // HAVE_SYS_TYPES_H #ifdef _MSC_VER @@ -86,36 +84,11 @@ typedef uint32_t pid_t; #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#define S_IFDIR _S_IFDIR - -#ifndef S_ISDIR -#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) -#endif - -#endif // _MSC_VER - -// Various useful posix functions that are not present in Windows. We provide -// custom implementations. -int vasprintf(char **ret, const char *fmt, va_list ap); -char *strcasestr(const char *s, const char *find); - -#ifdef _MSC_VER - -char *basename(char *path); -char *dirname(char *path); - -int strcasecmp(const char *s1, const char *s2); -int strncasecmp(const char *s1, const char *s2, size_t n); - #endif // _MSC_VER // empty functions inline int posix_openpt(int flag) { LLVM_BUILTIN_UNREACHABLE; } -inline int strerror_r(int errnum, char *buf, size_t buflen) { - LLVM_BUILTIN_UNREACHABLE; -} - inline int unlockpt(int fd) { LLVM_BUILTIN_UNREACHABLE; } inline int grantpt(int fd) { LLVM_BUILTIN_UNREACHABLE; } inline char *ptsname(int fd) { LLVM_BUILTIN_UNREACHABLE; } diff --git a/gnu/llvm/lldb/include/lldb/Host/windows/windows.h b/gnu/llvm/lldb/include/lldb/Host/windows/windows.h index 11594c658c1..d53d4b99672 100644 --- a/gnu/llvm/lldb/include/lldb/Host/windows/windows.h +++ b/gnu/llvm/lldb/include/lldb/Host/windows/windows.h @@ -17,9 +17,10 @@ #undef NOMINMAX // undef a previous definition to avoid warning #define NOMINMAX #include +#undef CreateProcess +#undef GetMessage #undef GetUserName #undef LoadImage -#undef CreateProcess #undef Yield #undef far #undef near diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandCompletions.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandCompletions.h index c80bde0e719..c13bc4997ff 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandCompletions.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandCompletions.h @@ -13,6 +13,7 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Core/SearchFilter.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/lldb-private.h" @@ -151,6 +152,15 @@ public: static void TypeCategoryNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + + /// This completer works for commands whose only arguments are a command path. + /// It isn't tied to an argument type because it completes not on a single + /// argument but on the sequence of arguments, so you have to invoke it by + /// hand. + static void + CompleteModifiableCmdPathArgs(CommandInterpreter &interpreter, + CompletionRequest &request, + OptionElementVector &opt_element_vector); }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandHistory.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandHistory.h index 12c170ba5ee..aa3018573fd 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandHistory.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandHistory.h @@ -10,6 +10,7 @@ #define LLDB_INTERPRETER_COMMANDHISTORY_H #include +#include #include #include @@ -28,7 +29,7 @@ public: bool IsEmpty() const; - llvm::Optional FindString(llvm::StringRef input_str) const; + std::optional FindString(llvm::StringRef input_str) const; llvm::StringRef GetStringAtIndex(size_t idx) const; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandInterpreter.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandInterpreter.h index 3b3daced3e3..38ff061612b 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -26,6 +26,7 @@ #include "lldb/lldb-private.h" #include +#include #include namespace lldb_private { @@ -223,21 +224,30 @@ public: eBroadcastBitAsynchronousErrorData = (1 << 4) }; - enum ChildrenTruncatedWarningStatus // tristate boolean to manage children - // truncation warning - { eNoTruncation = 0, // never truncated - eUnwarnedTruncation = 1, // truncated but did not notify - eWarnedTruncation = 2 // truncated and notified + /// Tristate boolean to manage children omission warnings. + enum ChildrenOmissionWarningStatus { + eNoOmission = 0, ///< No children were omitted. + eUnwarnedOmission = 1, ///< Children omitted, and not yet notified. + eWarnedOmission = 2 ///< Children omitted and notified. }; enum CommandTypes { - eCommandTypesBuiltin = 0x0001, // native commands such as "frame" - eCommandTypesUserDef = 0x0002, // scripted commands - eCommandTypesAliases = 0x0004, // aliases such as "po" - eCommandTypesHidden = 0x0008, // commands prefixed with an underscore - eCommandTypesAllThem = 0xFFFF // all commands + eCommandTypesBuiltin = 0x0001, //< native commands such as "frame" + eCommandTypesUserDef = 0x0002, //< scripted commands + eCommandTypesUserMW = 0x0004, //< multiword commands (command containers) + eCommandTypesAliases = 0x0008, //< aliases such as "po" + eCommandTypesHidden = 0x0010, //< commands prefixed with an underscore + eCommandTypesAllThem = 0xFFFF //< all commands }; + // The CommandAlias and CommandInterpreter both have a hand in + // substituting for alias commands. They work by writing special tokens + // in the template form of the Alias command, and then detecting them when the + // command is executed. These are the special tokens: + static const char *g_no_argument; + static const char *g_need_argument; + static const char *g_argument; + CommandInterpreter(Debugger &debugger, bool synchronous_execution); ~CommandInterpreter() override = default; @@ -251,13 +261,14 @@ public: } void SourceInitFileCwd(CommandReturnObject &result); - void SourceInitFileHome(CommandReturnObject &result, bool is_repl = false); + void SourceInitFileHome(CommandReturnObject &result, bool is_repl); + void SourceInitFileGlobal(CommandReturnObject &result); bool AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace); - bool AddUserCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, - bool can_replace); + Status AddUserCommand(llvm::StringRef name, + const lldb::CommandObjectSP &cmd_sp, bool can_replace); lldb::CommandObjectSP GetCommandSPExact(llvm::StringRef cmd, bool include_aliases = false) const; @@ -266,12 +277,49 @@ public: StringList *matches = nullptr, StringList *descriptions = nullptr) const; + CommandObject *GetUserCommandObject(llvm::StringRef cmd, + StringList *matches = nullptr, + StringList *descriptions = nullptr) const; + + /// Determine whether a root level, built-in command with this name exists. bool CommandExists(llvm::StringRef cmd) const; + /// Determine whether an alias command with this name exists bool AliasExists(llvm::StringRef cmd) const; + /// Determine whether a root-level user command with this name exists. bool UserCommandExists(llvm::StringRef cmd) const; + /// Determine whether a root-level user multiword command with this name + /// exists. + bool UserMultiwordCommandExists(llvm::StringRef cmd) const; + + /// Look up the command pointed to by path encoded in the arguments of + /// the incoming command object. If all the path components exist + /// and are all actual commands - not aliases, and the leaf command is a + /// multiword command, return the command. Otherwise return nullptr, and put + /// a useful diagnostic in the Status object. + /// + /// \param[in] path + /// An Args object holding the path in its arguments + /// \param[in] leaf_is_command + /// If true, return the container of the leaf name rather than looking up + /// the whole path as a leaf command. The leaf needn't exist in this case. + /// \param[in,out] result + /// If the path is not found, this error shows where we got off track. + /// \return + /// If found, a pointer to the CommandObjectMultiword pointed to by path, + /// or to the container of the leaf element is is_leaf_command. + /// Returns nullptr under two circumstances: + /// 1) The command in not found (check error.Fail) + /// 2) is_leaf is true and the path has only a leaf. We don't have a + /// dummy "contains everything MWC, so we return null here, but + /// in this case error.Success is true. + + CommandObjectMultiword *VerifyUserMultiwordCmdPath(Args &path, + bool leaf_is_command, + Status &result); + CommandAlias *AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, llvm::StringRef args_string = llvm::StringRef()); @@ -283,6 +331,11 @@ public: bool GetAliasFullName(llvm::StringRef cmd, std::string &full_name) const; + bool RemoveUserMultiword(llvm::StringRef multiword_name); + + // Do we want to allow top-level user multiword commands to be deleted? + void RemoveAllUserMultiword() { m_user_mw_dict.clear(); } + bool RemoveUser(llvm::StringRef alias_name); void RemoveAllUser() { m_user_dict.clear(); } @@ -354,7 +407,7 @@ public: /// Returns the auto-suggestion string that should be added to the given /// command line. - llvm::Optional GetAutoSuggestionForCommand(llvm::StringRef line); + std::optional GetAutoSuggestionForCommand(llvm::StringRef line); // This handles command line completion. void HandleCompletion(CompletionRequest &request); @@ -414,6 +467,8 @@ public: bool HasUserCommands() const; + bool HasUserMultiwordCommands() const; + bool HasAliasOptions() const; void BuildAliasCommandArgs(CommandObject *alias_cmd_obj, @@ -421,6 +476,7 @@ public: std::string &raw_input_string, CommandReturnObject &result); + /// Picks the number out of a string of the form "%NNN", otherwise return 0. int GetOptionArgumentPosition(const char *in_string); void SkipLLDBInitFiles(bool skip_lldbinit_files) { @@ -437,7 +493,8 @@ public: StringList &commands_help, bool search_builtin_commands, bool search_user_commands, - bool search_alias_commands); + bool search_alias_commands, + bool search_user_mw_commands); bool GetBatchCommandMode() { return m_batch_command_mode; } @@ -448,21 +505,33 @@ public: } void ChildrenTruncated() { - if (m_truncation_warning == eNoTruncation) - m_truncation_warning = eUnwarnedTruncation; + if (m_truncation_warning == eNoOmission) + m_truncation_warning = eUnwarnedOmission; } - bool TruncationWarningNecessary() { - return (m_truncation_warning == eUnwarnedTruncation); + void SetReachedMaximumDepth() { + if (m_max_depth_warning == eNoOmission) + m_max_depth_warning = eUnwarnedOmission; } - void TruncationWarningGiven() { m_truncation_warning = eWarnedTruncation; } + void PrintWarningsIfNecessary(Stream &s, const std::string &cmd_name) { + if (m_truncation_warning == eUnwarnedOmission) { + s.Printf("*** Some of the displayed variables have more members than the " + "debugger will show by default. To show all of them, you can " + "either use the --show-all-children option to %s or raise the " + "limit by changing the target.max-children-count setting.\n", + cmd_name.c_str()); + m_truncation_warning = eWarnedOmission; + } - const char *TruncationWarningText() { - return "*** Some of your variables have more members than the debugger " - "will show by default. To show all of them, you can either use the " - "--show-all-children option to %s or raise the limit by changing " - "the target.max-children-count setting.\n"; + if (m_max_depth_warning == eUnwarnedOmission) { + s.Printf("*** Some of the displayed variables have a greater depth of " + "members than the debugger will show by default. To increase " + "the limit, use the --depth option to %s, or raise the limit by " + "changing the target.max-children-depth setting.\n", + cmd_name.c_str()); + m_max_depth_warning = eWarnedOmission; + } } CommandHistory &GetCommandHistory() { return m_command_history; } @@ -491,6 +560,9 @@ public: bool GetSaveSessionOnQuit() const; void SetSaveSessionOnQuit(bool enable); + bool GetOpenTranscriptInEditor() const; + void SetOpenTranscriptInEditor(bool enable); + FileSpec GetSaveSessionDirectory() const; void SetSaveSessionDirectory(llvm::StringRef path); @@ -501,11 +573,17 @@ public: void SetEchoCommentCommands(bool enable); bool GetRepeatPreviousCommand() const; + + bool GetRequireCommandOverwrite() const; const CommandObject::CommandMap &GetUserCommands() const { return m_user_dict; } + const CommandObject::CommandMap &GetUserMultiwordCommands() const { + return m_user_mw_dict; + } + const CommandObject::CommandMap &GetCommands() const { return m_command_dict; } @@ -522,7 +600,7 @@ public: /// \return True if the exit code was successfully set; false if the /// interpreter doesn't allow custom exit codes. /// \see AllowExitCodeOnQuit - LLVM_NODISCARD bool SetQuitExitCode(int exit_code); + [[nodiscard]] bool SetQuitExitCode(int exit_code); /// Returns the exit code that the user has specified when running the /// 'quit' command. @@ -550,10 +628,14 @@ public: /// \return \b true if the session transcript was successfully written to /// disk, \b false otherwise. bool SaveTranscript(CommandReturnObject &result, - llvm::Optional output_file = llvm::None); + std::optional output_file = std::nullopt); FileSpec GetCurrentSourceDir(); + bool IsInteractive(); + + bool IOHandlerInterrupt(IOHandler &io_handler) override; + protected: friend class Debugger; @@ -567,8 +649,6 @@ protected: return ConstString(); } - bool IOHandlerInterrupt(IOHandler &io_handler) override; - void GetProcessOutput(); bool DidProcessStopAbnormally() const; @@ -598,10 +678,11 @@ private: void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, StringList &commands_help, - CommandObject::CommandMap &command_map); + const CommandObject::CommandMap &command_map); // An interruptible wrapper around the stream output - void PrintCommandOutput(Stream &stream, llvm::StringRef str); + void PrintCommandOutput(IOHandler &io_handler, llvm::StringRef str, + bool is_stdout); bool EchoCommandNonInteractive(llvm::StringRef line, const Flags &io_handler_flags) const; @@ -636,15 +717,20 @@ private: CommandObject::CommandMap m_alias_dict; // Stores user aliases/abbreviations for commands CommandObject::CommandMap m_user_dict; // Stores user-defined commands + CommandObject::CommandMap + m_user_mw_dict; // Stores user-defined multiword commands CommandHistory m_command_history; std::string m_repeat_command; // Stores the command that will be executed for // an empty command string. lldb::IOHandlerSP m_command_io_handler_sp; char m_comment_char; bool m_batch_command_mode; - ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated - // children and whether - // the user has been told + /// Whether we truncated a value's list of children and whether the user has + /// been told. + ChildrenOmissionWarningStatus m_truncation_warning; + /// Whether we reached the maximum child nesting depth and whether the user + /// has been told. + ChildrenOmissionWarningStatus m_max_depth_warning; // FIXME: Stop using this to control adding to the history and then replace // this with m_command_source_dirs.size(). @@ -657,7 +743,7 @@ private: // The exit code the user has requested when calling the 'quit' command. // No value means the user hasn't set a custom exit code so far. - llvm::Optional m_quit_exit_code; + std::optional m_quit_exit_code; // If the driver is accepts custom exit codes for the 'quit' command. bool m_allow_exit_code = false; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandObject.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandObject.h index 8bc5d3e2235..86750a49bd3 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandObject.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandObject.h @@ -10,6 +10,8 @@ #define LLDB_INTERPRETER_COMMANDOBJECT_H #include +#include +#include #include #include @@ -64,7 +66,7 @@ size_t FindLongestCommandWord(std::map &dict) { return max_len; } -class CommandObject { +class CommandObject : public std::enable_shared_from_this { public: typedef llvm::StringRef(ArgumentHelpCallbackFunction)(); @@ -77,17 +79,18 @@ public: explicit operator bool() const { return (help_callback != nullptr); } }; - struct ArgumentTableEntry // Entries in the main argument information table - { + /// Entries in the main argument information table. + struct ArgumentTableEntry { lldb::CommandArgumentType arg_type; const char *arg_name; CommandCompletions::CommonCompletionTypes completion_type; + OptionEnumValues enum_values; ArgumentHelpCallback help_function; const char *help_text; }; - struct CommandArgumentData // Used to build individual command argument lists - { + /// Used to build individual command argument lists. + struct CommandArgumentData { lldb::CommandArgumentType arg_type; ArgumentRepetitionType arg_repetition; /// This arg might be associated only with some particular option set(s). By @@ -104,9 +107,6 @@ public: typedef std::vector CommandArgumentEntry; // Used to build individual command argument lists - static ArgumentTableEntry g_arguments_data - [lldb::eArgTypeLastArg]; // Main argument information table - typedef std::map CommandMap; CommandObject(CommandInterpreter &interpreter, llvm::StringRef name, @@ -145,6 +145,10 @@ public: virtual bool IsMultiwordObject() { return false; } + bool IsUserCommand() { return m_is_user_command; } + + void SetIsUserCommand(bool is_user) { m_is_user_command = is_user; } + virtual CommandObjectMultiword *GetAsMultiwordCommand() { return nullptr; } virtual bool IsAlias() { return false; } @@ -159,16 +163,15 @@ public: return lldb::CommandObjectSP(); } + virtual lldb::CommandObjectSP GetSubcommandSPExact(llvm::StringRef sub_cmd) { + return lldb::CommandObjectSP(); + } + virtual CommandObject *GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches = nullptr) { return nullptr; } - virtual void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) {} - void FormatLongHelpText(Stream &output_strm, llvm::StringRef long_help); void GenerateHelpText(CommandReturnObject &result); @@ -183,6 +186,13 @@ public: return false; } + virtual llvm::Error LoadUserSubcommand(llvm::StringRef cmd_name, + const lldb::CommandObjectSP &command_obj, + bool can_replace) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "can only add commands to container commands"); + } + virtual bool WantsRawCommandString() = 0; // By default, WantsCompletion = !WantsRawCommandString. Subclasses who want @@ -192,8 +202,6 @@ public: virtual Options *GetOptions(); - static const ArgumentTableEntry *GetArgumentTable(); - static lldb::CommandArgumentType LookupArgumentName(llvm::StringRef arg_name); static const ArgumentTableEntry * @@ -266,14 +274,13 @@ public: /// The command arguments. /// /// \return - /// nullptr if there is no special repeat command - it will use the + /// std::nullopt 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 nullptr; + /// Otherwise a std::string containing the command to be repeated. + /// If the string is empty, the command won't be allow repeating. + virtual std::optional + GetRepeatCommand(Args ¤t_command_args, uint32_t index) { + return std::nullopt; } bool HasOverrideCallback() const { @@ -317,15 +324,20 @@ protected: } virtual const char *GetInvalidProcessDescription() { - return "invalid process"; + return "Command requires a current process."; } - virtual const char *GetInvalidThreadDescription() { return "invalid thread"; } + virtual const char *GetInvalidThreadDescription() { + return "Command requires a process which is currently stopped."; + } - virtual const char *GetInvalidFrameDescription() { return "invalid frame"; } + virtual const char *GetInvalidFrameDescription() { + return "Command requires a process, which is currently stopped."; + } virtual const char *GetInvalidRegContextDescription() { - return "invalid frame, no registers"; + return "invalid frame, no registers, command requires a process which is " + "currently stopped."; } // This is for use in the command interpreter, when you either want the @@ -367,6 +379,7 @@ protected: lldb::CommandOverrideCallback m_deprecated_command_override_callback; lldb::CommandOverrideCallbackWithResult m_command_override_callback; void *m_command_override_baton; + bool m_is_user_command = false; // Helper function to populate IDs or ID ranges as the command argument data // to the specified command argument entry. diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandObjectMultiword.h index f330a745f9b..1c14b492c80 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandObjectMultiword.h @@ -11,6 +11,7 @@ #include "lldb/Interpreter/CommandObject.h" #include "lldb/Utility/CompletionRequest.h" +#include namespace lldb_private { @@ -35,25 +36,28 @@ public: bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override; + llvm::Error LoadUserSubcommand(llvm::StringRef cmd_name, + const lldb::CommandObjectSP &command_obj, + bool can_replace) override; + + llvm::Error RemoveUserSubcommand(llvm::StringRef cmd_name, bool multiword_okay); + void GenerateHelpText(Stream &output_stream) override; lldb::CommandObjectSP GetSubcommandSP(llvm::StringRef sub_cmd, StringList *matches = nullptr) override; + lldb::CommandObjectSP GetSubcommandSPExact(llvm::StringRef sub_cmd) override; + CommandObject *GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches = nullptr) override; - void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) override; - bool WantsRawCommandString() override { return false; } void HandleCompletion(CompletionRequest &request) override; - const char *GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override; + std::optional GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override; bool Execute(const char *args_string, CommandReturnObject &result) override; @@ -102,11 +106,6 @@ public: CommandObject *GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches = nullptr) override; - void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) override; - bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override; @@ -122,8 +121,8 @@ public: HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override; - const char *GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override; + std::optional GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override; /// \return /// An error message to be displayed when the command is executed (i.e. diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h new file mode 100644 index 00000000000..233ad34ff0f --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h @@ -0,0 +1,271 @@ +//===-- CommandOptionArgumentTable.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H +#define LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H + +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +static constexpr OptionEnumValueElement g_corefile_save_style[] = { + {lldb::eSaveCoreFull, "full", "Create a core file with all memory saved"}, + {lldb::eSaveCoreDirtyOnly, "modified-memory", + "Create a corefile with only modified memory saved"}, + {lldb::eSaveCoreStackOnly, "stack", + "Create a corefile with only stack memory saved"}, +}; + +static constexpr OptionEnumValueElement g_description_verbosity_type[] = { + { + eLanguageRuntimeDescriptionDisplayVerbosityCompact, + "compact", + "Only show the description string", + }, + { + eLanguageRuntimeDescriptionDisplayVerbosityFull, + "full", + "Show the full output, including persistent variable's name and type", + }, +}; + +static constexpr OptionEnumValueElement g_sort_option_enumeration[] = { + { + eSortOrderNone, + "none", + "No sorting, use the original symbol table order.", + }, + { + eSortOrderByAddress, + "address", + "Sort output by symbol address.", + }, + { + eSortOrderByName, + "name", + "Sort output by symbol name.", + }, +}; + +// Note that the negation in the argument name causes a slightly confusing +// mapping of the enum values. +static constexpr OptionEnumValueElement g_dependents_enumeration[] = { + { + eLoadDependentsDefault, + "default", + "Only load dependents when the target is an executable.", + }, + { + eLoadDependentsNo, + "true", + "Don't load dependents, even if the target is an executable.", + }, + { + eLoadDependentsYes, + "false", + "Load dependents, even if the target is not an executable.", + }, +}; + +// FIXME: "script-type" needs to have its contents determined dynamically, so +// somebody can add a new scripting language to lldb and have it pickable here +// without having to change this enumeration by hand and rebuild lldb proper. +static constexpr OptionEnumValueElement g_script_option_enumeration[] = { + { + lldb::eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + lldb::eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + lldb::eScriptLanguageLua, + "lua", + "Commands are in the Lua language.", + }, + { + lldb::eScriptLanguageNone, + "default", + "Commands are in the default scripting language.", + }, +}; + +static constexpr OptionEnumValueElement g_log_handler_type[] = { + { + eLogHandlerDefault, + "default", + "Use the default (stream) log handler", + }, + { + eLogHandlerStream, + "stream", + "Write log messages to the debugger output stream or to a file if one " + "is specified. A buffer size (in bytes) can be specified with -b. If " + "no buffer size is specified the output is unbuffered.", + }, + { + eLogHandlerCircular, + "circular", + "Write log messages to a fixed size circular buffer. A buffer size " + "(number of messages) must be specified with -b.", + }, + { + eLogHandlerSystem, + "os", + "Write log messages to the operating system log.", + }, +}; + +static constexpr OptionEnumValueElement g_script_synchro_type[] = { + { + eScriptedCommandSynchronicitySynchronous, + "synchronous", + "Run synchronous", + }, + { + eScriptedCommandSynchronicityAsynchronous, + "asynchronous", + "Run asynchronous", + }, + { + eScriptedCommandSynchronicityCurrentValue, + "current", + "Do not alter current setting", + }, +}; + +static constexpr OptionEnumValueElement g_running_mode[] = { + {lldb::eOnlyThisThread, "this-thread", "Run only this thread"}, + {lldb::eAllThreads, "all-threads", "Run all threads"}, + {lldb::eOnlyDuringStepping, "while-stepping", + "Run only this thread while stepping"}, +}; + +llvm::StringRef RegisterNameHelpTextCallback(); +llvm::StringRef BreakpointIDHelpTextCallback(); +llvm::StringRef BreakpointIDRangeHelpTextCallback(); +llvm::StringRef BreakpointNameHelpTextCallback(); +llvm::StringRef GDBFormatHelpTextCallback(); +llvm::StringRef FormatHelpTextCallback(); +llvm::StringRef LanguageTypeHelpTextCallback(); +llvm::StringRef SummaryStringHelpTextCallback(); +llvm::StringRef ExprPathHelpTextCallback(); +llvm::StringRef arch_helper(); + +static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = { + // clang-format off + { lldb::eArgTypeAddress, "address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A valid address in the target program's execution space." }, + { lldb::eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An expression that resolves to an address." }, + { lldb::eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." }, + { lldb::eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, + { lldb::eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, {}, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." }, + { lldb::eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, + { lldb::eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, {}, { BreakpointIDHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, {}, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, {}, { BreakpointNameHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Number of bytes to use." }, + { lldb::eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Then name of a class from the debug information in the program." }, + { lldb::eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, + { lldb::eArgTypeCount, "count", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An unsigned integer." }, + { lldb::eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, g_description_verbosity_type, { nullptr, false }, "How verbose the output of 'po' should be." }, + { lldb::eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, {}, { nullptr, false }, "A directory name." }, + { lldb::eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eDisassemblyFlavorCompletion, {}, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, + { lldb::eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, {}, { ExprPathHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, + { lldb::eArgTypeFileLineColumn, "linespec", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A source specifier in the form file:line[:column]" }, + { lldb::eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, {}, { nullptr, false }, "The name of a file (can include path)." }, + { lldb::eArgTypeFormat, "format", CommandCompletions::eNoCompletion, {}, { FormatHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeFrameIndex, "frame-index", CommandCompletions::eFrameIndexCompletion, {}, { nullptr, false }, "Index into a thread's list of frames." }, + { lldb::eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a function." }, + { lldb::eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a function or symbol." }, + { lldb::eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, {}, { GDBFormatHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, + { lldb::eArgTypeIndex, "index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An index into a list." }, + { lldb::eArgTypeLanguage, "source-language", CommandCompletions::eTypeLanguageCompletion, {}, { LanguageTypeHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Line number in a source file." }, + { lldb::eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, + { lldb::eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, + { lldb::eArgTypeMethod, "method", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A C++ method name." }, + { lldb::eArgTypeName, "name", CommandCompletions::eTypeCategoryNameCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The number of lines to use." }, + { lldb::eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The number of items per line to display." }, + { lldb::eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A command that is entered as a single line of text." }, + { lldb::eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, {}, { nullptr, false }, "Path." }, + { lldb::eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." }, + { lldb::eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." }, + { lldb::eArgTypePid, "pid", CommandCompletions::eProcessIDCompletion, {}, { nullptr, false }, "The process ID number." }, + { lldb::eArgTypePlugin, "plugin", CommandCompletions::eProcessPluginCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeProcessName, "process-name", CommandCompletions::eProcessNameCompletion, {}, { nullptr, false }, "The name of the process." }, + { lldb::eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a Python class." }, + { lldb::eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a Python function." }, + { lldb::eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Source code written in Python." }, + { lldb::eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of the thread queue." }, + { lldb::eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, {}, { RegisterNameHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A POSIX-compliant extended regular expression." }, + { lldb::eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." }, + { lldb::eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, g_running_mode, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, g_script_synchro_type, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." }, + { lldb::eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, g_script_option_enumeration, { nullptr, false }, "The scripting language to be used for script-based commands. Supported languages are python and lua." }, + { lldb::eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Any word of interest for search purposes." }, + { lldb::eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An Objective-C selector name." }, + { lldb::eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, + { lldb::eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, + { lldb::eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, + { lldb::eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, + { lldb::eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a shared library." }, + { lldb::eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, {}, { nullptr, false }, "The name of a source file.." }, + { lldb::eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, g_sort_option_enumeration, { nullptr, false }, "Specify a sort order when dumping lists." }, + { lldb::eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, {}, { SummaryStringHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, {}, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" }, + { lldb::eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Thread ID number." }, + { lldb::eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Index into the process' list of threads." }, + { lldb::eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The thread's name." }, + { lldb::eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A type name." }, + { lldb::eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An unsigned integer." }, + { lldb::eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, + { lldb::eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, {} ,{ nullptr, false }, "The name of a variable in your program." }, + { lldb::eArgTypeValue, "value", CommandCompletions::eNoCompletion, g_dependents_enumeration, { nullptr, false }, "A value could be anything, depending on where and how it is used." }, + { lldb::eArgTypeWidth, "width", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNone, "none", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "No help available for this." }, + { lldb::eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, {}, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." }, + { lldb::eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Watchpoint IDs are positive integers." }, + { lldb::eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "For example, '1-3' or '1 to 3'." }, + { lldb::eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Specify the type for a watchpoint." }, + { lldb::eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }, + { lldb::eArgTypeCommand, "command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An LLDB Command line command element." }, + { lldb::eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Column number in a source file." }, + { lldb::eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, {}, { nullptr, false }, "A module UUID value." }, + { lldb::eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, g_corefile_save_style, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }, + { lldb::eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, g_log_handler_type ,{ nullptr, false }, "The log handle that will be used to write out log messages." }, + { lldb::eArgTypeSEDStylePair, "substitution-pair", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A sed-style pattern and target pair." }, + { lldb::eArgTypeRecognizerID, "frame-recognizer-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The ID for a stack frame recognizer." }, + { lldb::eArgTypeConnectURL, "process-connect-url", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A URL-style specification for a remote connection." }, + { lldb::eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The index ID for an lldb Target." }, + { lldb::eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The ID you receive when you create a stop-hook." }, + // clang-format on +}; + +static_assert((sizeof(g_argument_table) / + sizeof(CommandObject::ArgumentTableEntry)) == + lldb::eArgTypeLastArg, + "number of elements in g_argument_table doesn't match " + "CommandArgumentType enumeration"); + +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/CommandReturnObject.h b/gnu/llvm/lldb/include/lldb/Interpreter/CommandReturnObject.h index 0c995b73c46..2177e721f9a 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -15,6 +15,7 @@ #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/WithColor.h" @@ -132,15 +133,17 @@ public: void SetError(const Status &error, const char *fallback_error_cstr = nullptr); - lldb::ReturnStatus GetStatus(); + void SetError(llvm::Error error); + + lldb::ReturnStatus GetStatus() const; void SetStatus(lldb::ReturnStatus status); - bool Succeeded(); + bool Succeeded() const; - bool HasResult(); + bool HasResult() const; - bool GetDidChangeProcessState(); + bool GetDidChangeProcessState() const; void SetDidChangeProcessState(bool b); diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupFormat.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupFormat.h index 2d445b8a6c2..551688b0d25 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupFormat.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupFormat.h @@ -16,6 +16,9 @@ namespace lldb_private { +typedef std::vector> + OptionGroupFormatUsageTextVector; + // OptionGroupFormat class OptionGroupFormat : public OptionGroup { @@ -30,7 +33,10 @@ 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 + UINT64_MAX, // Pass UINT64_MAX to disable the "--count" option + OptionGroupFormatUsageTextVector usage_text_vector = {} + // Use to override default option usage text with the command specific one + ); ~OptionGroupFormat() override = default; @@ -73,6 +79,7 @@ protected: char m_prev_gdb_format; char m_prev_gdb_size; bool m_has_gdb_format; + OptionDefinition m_option_definitions[4]; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h new file mode 100644 index 00000000000..918ea3ad96d --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h @@ -0,0 +1,44 @@ +//===-- OptionGroupMemoryTag.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_OPTIONGROUPMEMORYTAG_H +#define LLDB_INTERPRETER_OPTIONGROUPMEMORYTAG_H + +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +class OptionGroupMemoryTag : public OptionGroup { +public: + OptionGroupMemoryTag( + // Whether to note that --show-tags does not apply to binary output. + // "memory read" wants this but "memory find" does not. + bool note_binary = false); + + ~OptionGroupMemoryTag() override = default; + + llvm::ArrayRef GetDefinitions() override; + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + bool AnyOptionWasSet() const { return m_show_tags.OptionWasSet(); } + + OptionValueBoolean GetShowTags() { return m_show_tags; }; + +protected: + OptionValueBoolean m_show_tags; + OptionDefinition m_option_definition; +}; + +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_OPTIONGROUPMEMORYTAG_H diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h index 56452f4956f..9b545c46fba 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -43,7 +43,8 @@ public: lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP()); bool show_types : 1, show_location : 1, flat_output : 1, use_objc : 1, - use_synth : 1, be_raw : 1, ignore_cap : 1, run_validator : 1; + use_synth : 1, be_raw : 1, ignore_cap : 1, run_validator : 1, + max_depth_is_default : 1; uint32_t no_summary_depth; uint32_t max_depth; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValue.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValue.h index 99f52b0411b..3c842d1f5ce 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValue.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValue.h @@ -17,6 +17,7 @@ #include "lldb/lldb-defines.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" +#include "llvm/Support/JSON.h" namespace lldb_private { @@ -82,6 +83,16 @@ public: virtual void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) = 0; + // TODO: make this function pure virtual after implementing it in all + // child classes. + virtual llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) { + // Return nullptr which will create a llvm::json::Value() that is a NULL + // value. No setting should ever really have a NULL value in JSON. This + // indicates an error occurred and if/when we add a FromJSON() it will know + // to fail if someone tries to set it with a NULL JSON value. + return nullptr; + } + virtual Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign); @@ -311,7 +322,6 @@ public: lldb::OptionValueSP GetParent() const { return m_parent_wp.lock(); } void SetValueChangedCallback(std::function callback) { - assert(!m_callback); m_callback = std::move(callback); } diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueArray.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueArray.h index 011eefc3425..147e15ef433 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueArray.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueArray.h @@ -18,7 +18,7 @@ namespace lldb_private { class OptionValueArray : public Cloneable { public: OptionValueArray(uint32_t type_mask = UINT32_MAX, bool raw_value_dump = false) - : m_type_mask(type_mask), m_values(), m_raw_value_dump(raw_value_dump) {} + : m_type_mask(type_mask), m_raw_value_dump(raw_value_dump) {} ~OptionValueArray() override = default; @@ -29,6 +29,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueBoolean.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueBoolean.h index fd15ccb12c4..01e7c6c09d8 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueBoolean.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueBoolean.h @@ -29,6 +29,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueChar.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueChar.h index 6b8a314a7c9..32ec2bb59fc 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueChar.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueChar.h @@ -30,6 +30,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueDictionary.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueDictionary.h index f96cbc9fe9e..1fdccdeccef 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueDictionary.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueDictionary.h @@ -12,6 +12,7 @@ #include #include "lldb/Interpreter/OptionValue.h" +#include "lldb/lldb-private-types.h" namespace lldb_private { @@ -19,8 +20,10 @@ class OptionValueDictionary : public Cloneable { public: OptionValueDictionary(uint32_t type_mask = UINT32_MAX, + OptionEnumValues enum_values = OptionEnumValues(), bool raw_value_dump = true) - : m_type_mask(type_mask), m_raw_value_dump(raw_value_dump) {} + : m_type_mask(type_mask), m_enum_values(enum_values), + m_raw_value_dump(raw_value_dump) {} ~OptionValueDictionary() override = default; @@ -31,6 +34,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; @@ -75,6 +80,7 @@ public: protected: typedef std::map collection; uint32_t m_type_mask; + OptionEnumValues m_enum_values; collection m_values; bool m_raw_value_dump; }; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFileSpec.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFileSpec.h index 6648bbac93e..b680a89688d 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFileSpec.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFileSpec.h @@ -35,6 +35,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value.GetPath(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormat.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormat.h index 1f2c66b164d..5be885fe4f7 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormat.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormat.h @@ -31,6 +31,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h index cb8b2ef13fa..b8ef03a44d0 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueFormatEntity.h @@ -28,6 +28,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueLanguage.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueLanguage.h index c00f71ffff3..f20a2c64f69 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueLanguage.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueLanguage.h @@ -33,6 +33,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValuePathMappings.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValuePathMappings.h index 4bc65ce76c7..82a968a77c1 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValuePathMappings.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValuePathMappings.h @@ -29,6 +29,8 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueProperties.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueProperties.h index 6fa5403ac14..7c344dc23a0 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueProperties.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueProperties.h @@ -47,11 +47,13 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override; + ConstString GetName() const override { return m_name; } virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, Stream &strm, llvm::StringRef property_path, - uint32_t dump_mask); + uint32_t dump_mask, bool is_json = false); virtual void DumpAllDescriptions(CommandInterpreter &interpreter, Stream &strm) const; @@ -114,6 +116,9 @@ public: GetPropertyAtIndexAsOptionValueLanguage(const ExecutionContext *exe_ctx, uint32_t idx) const; + bool SetPropertyAtIndexAsLanguage(const ExecutionContext *exe_ctx, + uint32_t idx, lldb::LanguageType lang); + bool GetPropertyAtIndexAsArgs(const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const; @@ -149,6 +154,10 @@ public: GetPropertyAtIndexAsOptionValueSInt64(const ExecutionContext *exe_ctx, uint32_t idx) const; + OptionValueUInt64 * + GetPropertyAtIndexAsOptionValueUInt64(const ExecutionContext *exe_ctx, + uint32_t idx) const; + int64_t GetPropertyAtIndexAsSInt64(const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueRegex.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueRegex.h index 129987484f1..3c188003ceb 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueRegex.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueRegex.h @@ -28,6 +28,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_regex.GetText(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueSInt64.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueSInt64.h index 3493eb1037c..5efae627758 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueSInt64.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueSInt64.h @@ -35,6 +35,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueString.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueString.h index be42deb80da..becf35f8e88 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueString.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueString.h @@ -69,6 +69,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; @@ -110,6 +114,11 @@ public: bool IsDefaultValueEmpty() const { return m_default_value.empty(); } + void SetValidator(ValidatorCallback validator, void *baton = nullptr) { + m_validator = validator; + m_validator_baton = baton; + } + protected: std::string m_current_value; std::string m_default_value; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUInt64.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUInt64.h index f212b2a19de..30c27bf73d9 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUInt64.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUInt64.h @@ -38,6 +38,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_current_value; + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUUID.h b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUUID.h index 0ed490d1811..e0e4235fdf0 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUUID.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/OptionValueUUID.h @@ -29,6 +29,10 @@ public: void DumpValue(const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) override; + llvm::json::Value ToJSON(const ExecutionContext *exe_ctx) override { + return m_uuid.GetAsString(); + } + Status SetValueFromString(llvm::StringRef value, VarSetOperationType op = eVarSetOperationAssign) override; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/Options.h b/gnu/llvm/lldb/include/lldb/Interpreter/Options.h index 6bf5c21fe98..a952d5f78df 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/Options.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/Options.h @@ -86,7 +86,7 @@ public: const OptionDefinition &option_def, uint32_t output_max_columns); - void GenerateOptionUsage(Stream &strm, CommandObject *cmd, + void GenerateOptionUsage(Stream &strm, CommandObject &cmd, uint32_t screen_width); bool SupportsLongOption(const char *long_option); @@ -169,7 +169,7 @@ public: /// user wants returned. /// /// \return - /// \btrue if we were in an option, \bfalse otherwise. + /// \b true if we were in an option, \b false otherwise. bool HandleOptionCompletion(lldb_private::CompletionRequest &request, OptionElementVector &option_map, CommandInterpreter &interpreter); diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/Property.h b/gnu/llvm/lldb/include/lldb/Interpreter/Property.h index 97ec7ca1d4a..09f09358e8a 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/Property.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/Property.h @@ -10,7 +10,6 @@ #define LLDB_INTERPRETER_PROPERTY_H #include "lldb/Interpreter/OptionValue.h" -#include "lldb/Utility/ConstString.h" #include "lldb/Utility/Flags.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-private-types.h" @@ -37,13 +36,11 @@ class Property { public: Property(const PropertyDefinition &definition); - Property(ConstString name, ConstString desc, bool is_global, + Property(llvm::StringRef name, llvm::StringRef desc, bool is_global, const lldb::OptionValueSP &value_sp); - llvm::StringRef GetName() const { return m_name.GetStringRef(); } - llvm::StringRef GetDescription() const { - return m_description.GetStringRef(); - } + llvm::StringRef GetName() const { return m_name; } + llvm::StringRef GetDescription() const { return m_description; } const lldb::OptionValueSP &GetValue() const { return m_value_sp; } @@ -67,8 +64,8 @@ public: void SetValueChangedCallback(std::function callback); protected: - ConstString m_name; - ConstString m_description; + std::string m_name; + std::string m_description; lldb::OptionValueSP m_value_sp; bool m_is_global; }; diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 80a054b32ce..4d073995def 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -11,17 +11,20 @@ #include "lldb/API/SBData.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBMemoryRegionInfo.h" #include "lldb/Breakpoint/BreakpointOptions.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Host/PseudoTerminal.h" +#include "lldb/Interpreter/ScriptedPlatformInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" #include "lldb/lldb-private.h" +#include namespace lldb_private { @@ -118,7 +121,7 @@ private: lldb::FileSP m_input_file_sp; lldb::StreamFileSP m_output_file_sp; lldb::StreamFileSP m_error_file_sp; - Communication m_communication; + ThreadedCommunication m_communication; bool m_disconnect; }; @@ -145,7 +148,11 @@ public: ScriptInterpreter( Debugger &debugger, lldb::ScriptLanguage script_lang, lldb::ScriptedProcessInterfaceUP scripted_process_interface_up = - std::make_unique()); + std::make_unique(), + lldb::ScriptedPlatformInterfaceUP scripted_platform_interface_up = + std::make_unique()); + + virtual StructuredData::DictionarySP GetInterpreterInfo(); ~ScriptInterpreter() override = default; @@ -271,7 +278,7 @@ public: virtual StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, - StructuredDataImpl *args_data, + const StructuredDataImpl &args_data, std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) { return StructuredData::ObjectSP(); @@ -307,7 +314,7 @@ public: virtual StructuredData::GenericSP CreateScriptedBreakpointResolver(const char *class_name, - StructuredDataImpl *args_data, + const StructuredDataImpl &args_data, lldb::BreakpointSP &bkpt_sp) { return StructuredData::GenericSP(); } @@ -327,7 +334,7 @@ public: virtual StructuredData::GenericSP CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name, - StructuredDataImpl *args_data, Status &error) { + const StructuredDataImpl &args_data, Status &error) { error.SetErrorString("Creating scripted stop-hooks with the current " "script interpreter is not supported."); return StructuredData::GenericSP(); @@ -415,6 +422,14 @@ public: return false; } + // Calls the specified formatter matching Python function and returns its + // result (true if it's a match, false if we should keep looking for a + // matching formatter). + virtual bool FormatterCallbackFunction(const char *function_name, + lldb::TypeImplSP type_impl_sp) { + return true; + } + virtual void Clear() { // Clean up any ref counts to SBObjects that might be in global variables } @@ -559,15 +574,23 @@ public: return *m_scripted_process_interface_up; } + ScriptedPlatformInterface &GetScriptedPlatformInterface() { + return *m_scripted_platform_interface_up; + } + lldb::DataExtractorSP GetDataExtractorFromSBData(const lldb::SBData &data) const; Status GetStatusFromSBError(const lldb::SBError &error) const; + std::optional GetOpaqueTypeFromSBMemoryRegionInfo( + const lldb::SBMemoryRegionInfo &mem_region) const; + protected: Debugger &m_debugger; lldb::ScriptLanguage m_script_lang; lldb::ScriptedProcessInterfaceUP m_scripted_process_interface_up; + lldb::ScriptedPlatformInterfaceUP m_scripted_platform_interface_up; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedInterface.h b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedInterface.h new file mode 100644 index 00000000000..da4977af123 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedInterface.h @@ -0,0 +1,75 @@ +//===-- ScriptedInterface.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_SCRIPTEDINTERFACE_H +#define LLDB_INTERPRETER_SCRIPTEDINTERFACE_H + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-private.h" + +#include "llvm/Support/Compiler.h" + +#include + +namespace lldb_private { +class ScriptedInterface { +public: + ScriptedInterface() = default; + virtual ~ScriptedInterface() = default; + + virtual StructuredData::GenericSP + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) = 0; + + template + static Ret ErrorWithMessage(llvm::StringRef caller_name, + llvm::StringRef error_msg, Status &error, + LLDBLog log_caterogy = LLDBLog::Process) { + LLDB_LOGF(GetLog(log_caterogy), "%s ERROR = %s", caller_name.data(), + error_msg.data()); + error.SetErrorString(llvm::Twine(caller_name + llvm::Twine(" ERROR = ") + + llvm::Twine(error_msg)) + .str()); + return {}; + } + + template + bool CheckStructuredDataObject(llvm::StringRef caller, T obj, Status &error) { + if (!obj) { + return ErrorWithMessage(caller, + llvm::Twine("Null StructuredData object (" + + llvm::Twine(error.AsCString()) + + llvm::Twine(").")) + .str(), + error); + } + + if (!obj->IsValid()) { + return ErrorWithMessage( + caller, + llvm::Twine("Invalid StructuredData object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + if (error.Fail()) + return ErrorWithMessage(caller, error.AsCString(), error); + + return true; + } + +protected: + StructuredData::GenericSP m_object_instance_sp; +}; +} // namespace lldb_private +#endif // LLDB_INTERPRETER_SCRIPTEDINTERFACE_H diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedMetadata.h b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedMetadata.h new file mode 100644 index 00000000000..00ebce323bf --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedMetadata.h @@ -0,0 +1,45 @@ +//===-- ScriptedMetadata.h ------------------------------------ -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_SCRIPTEDMETADATA_H +#define LLDB_INTERPRETER_SCRIPTEDMETADATA_H + +#include "OptionGroupPythonClassWithDict.h" + +#include "lldb/Host/Host.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Utility/StructuredData.h" + +namespace lldb_private { +class ScriptedMetadata { +public: + ScriptedMetadata(llvm::StringRef class_name, + StructuredData::DictionarySP dict_sp) + : m_class_name(class_name.data()), m_args_sp(dict_sp) {} + + ScriptedMetadata(const ProcessLaunchInfo &launch_info) { + m_class_name = launch_info.GetScriptedProcessClassName(); + m_args_sp = launch_info.GetScriptedProcessDictionarySP(); + } + + ScriptedMetadata(const OptionGroupPythonClassWithDict &option_group) { + auto opt_group = const_cast(option_group); + m_class_name = opt_group.GetName(); + m_args_sp = opt_group.GetStructuredData(); + } + + llvm::StringRef GetClassName() const { return m_class_name; } + StructuredData::DictionarySP GetArgsSP() const { return m_args_sp; } + +private: + std::string m_class_name; + StructuredData::DictionarySP m_args_sp; +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_SCRIPTEDMETADATA_H diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h new file mode 100644 index 00000000000..2db1fef0be7 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedPlatformInterface.h @@ -0,0 +1,49 @@ +//===-- ScriptedPlatformInterface.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H +#define LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H + +#include "lldb/Core/StructuredDataImpl.h" +#include "lldb/Interpreter/ScriptedInterface.h" + +#include "lldb/lldb-private.h" + +#include + +namespace lldb_private { +class ScriptedPlatformInterface : virtual public ScriptedInterface { +public: + StructuredData::GenericSP + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { + return {}; + } + + virtual StructuredData::DictionarySP ListProcesses() { return {}; } + + virtual StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) { + return {}; + } + + virtual Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) { + return Status("ScriptedPlatformInterface cannot attach to a process"); + } + + virtual Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) { + return Status("ScriptedPlatformInterface cannot launch process"); + } + + virtual Status KillProcess(lldb::pid_t pid) { + return Status("ScriptedPlatformInterface cannot kill process"); + } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_SCRIPTEDPLATFORMINTERFACE_H diff --git a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h index 223e89be87e..6d1860aa310 100644 --- a/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/gnu/llvm/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -10,22 +10,22 @@ #define LLDB_INTERPRETER_SCRIPTEDPROCESSINTERFACE_H #include "lldb/Core/StructuredDataImpl.h" -#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Interpreter/ScriptedInterface.h" +#include "lldb/Target/MemoryRegionInfo.h" + #include "lldb/lldb-private.h" +#include #include namespace lldb_private { -class ScriptedProcessInterface { +class ScriptedProcessInterface : virtual public ScriptedInterface { public: - ScriptedProcessInterface() : m_object_instance_sp(nullptr) {} - - virtual ~ScriptedProcessInterface() = default; - - virtual StructuredData::GenericSP - CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp, - StructuredData::DictionarySP args_sp) { - return nullptr; + StructuredData::GenericSP + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { + return {}; } virtual Status Launch() { return Status("ScriptedProcess did not launch"); } @@ -36,32 +36,74 @@ public: virtual Status Stop() { return Status("ScriptedProcess did not stop"); } - virtual lldb::MemoryRegionInfoSP - GetMemoryRegionContainingAddress(lldb::addr_t address) { - return nullptr; + virtual std::optional + GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) { + error.SetErrorString("ScriptedProcess have no memory region."); + return {}; } + virtual StructuredData::DictionarySP GetThreadsInfo() { return {}; } + virtual StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) { - return nullptr; + return {}; } virtual StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) { - return nullptr; + return {}; } virtual lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, Status &error) { - return nullptr; + return {}; } - virtual StructuredData::DictionarySP GetLoadedImages() { return nullptr; } + virtual StructuredData::ArraySP GetLoadedImages() { return {}; } virtual lldb::pid_t GetProcessID() { return LLDB_INVALID_PROCESS_ID; } virtual bool IsAlive() { return true; } -private: - StructuredData::ObjectSP m_object_instance_sp; + virtual std::optional GetScriptedThreadPluginName() { + return std::nullopt; + } + + virtual StructuredData::DictionarySP GetMetadata() { return {}; } + +protected: + friend class ScriptedThread; + virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() { + return {}; + } +}; + +class ScriptedThreadInterface : virtual public ScriptedInterface { +public: + StructuredData::GenericSP + CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { + return {}; + } + + virtual lldb::tid_t GetThreadID() { return LLDB_INVALID_THREAD_ID; } + + virtual std::optional GetName() { return std::nullopt; } + + virtual lldb::StateType GetState() { return lldb::eStateInvalid; } + + virtual std::optional GetQueue() { return std::nullopt; } + + virtual StructuredData::DictionarySP GetStopReason() { return {}; } + + virtual StructuredData::ArraySP GetStackFrames() { return {}; } + + virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; } + + virtual std::optional GetRegisterContext() { + return std::nullopt; + } + + virtual StructuredData::ArraySP GetExtendedInfo() { return {}; } }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Block.h b/gnu/llvm/lldb/include/lldb/Symbol/Block.h index de94556d3f2..02fd2add531 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Block.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Block.h @@ -338,6 +338,8 @@ public: Block *FindBlockByID(lldb::user_id_t block_id); + Block *FindInnermostBlockByOffset(const lldb::addr_t offset); + size_t GetNumRanges() const { return m_ranges.GetSize(); } bool GetRangeContainingOffset(const lldb::addr_t offset, Range &range); diff --git a/gnu/llvm/lldb/include/lldb/Symbol/CompactUnwindInfo.h b/gnu/llvm/lldb/include/lldb/Symbol/CompactUnwindInfo.h index ceb501e1c05..e38d0123ea7 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/CompactUnwindInfo.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/CompactUnwindInfo.h @@ -86,7 +86,7 @@ private: // valid for (start of the function) uint32_t valid_range_offset_end = 0; // the offset of the start of the next function - FunctionInfo() : lsda_address(), personality_ptr_address() {} + FunctionInfo() = default; }; struct UnwindHeader { @@ -138,9 +138,10 @@ private: ObjectFile &m_objfile; lldb::SectionSP m_section_sp; - lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is - // encrypted, read the - // sect contents + lldb::WritableDataBufferSP + m_section_contents_if_encrypted; // if the binary is + // encrypted, read the + // sect contents // out of live memory and cache them here std::mutex m_mutex; std::vector m_indexes; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/CompileUnit.h b/gnu/llvm/lldb/include/lldb/Symbol/CompileUnit.h index 2e52bca7097..44e1d673f1f 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/CompileUnit.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/CompileUnit.h @@ -208,9 +208,9 @@ public: /// unit file. /// /// \param[in] exact - /// If \btrue match only if there is a line table entry for this line + /// If \b true match only if there is a line table entry for this line /// number. - /// If \bfalse, find the line table entry equal to or after this line + /// If \b false, find the line table entry equal to or after this line /// number. /// /// \param[out] line_entry @@ -332,6 +332,7 @@ public: void SetLineTable(LineTable *line_table); void SetSupportFiles(const FileSpecList &support_files); + void SetSupportFiles(FileSpecList &&support_files); void SetDebugMacros(const DebugMacrosSP &debug_macros); @@ -442,6 +443,7 @@ private: CompileUnit(const CompileUnit &) = delete; const CompileUnit &operator=(const CompileUnit &) = delete; + const char *GetCachedLanguage() const; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Symbol/CompilerType.h b/gnu/llvm/lldb/include/lldb/Symbol/CompilerType.h index 0ad05a27570..c96fc5a2b68 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/CompilerType.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/CompilerType.h @@ -10,15 +10,18 @@ #define LLDB_SYMBOL_COMPILERTYPE_H #include +#include #include #include #include "lldb/lldb-private.h" #include "llvm/ADT/APSInt.h" +#include "llvm/Support/Casting.h" namespace lldb_private { class DataExtractor; +class TypeSystem; /// Generic representation of a type in a programming language. /// @@ -38,38 +41,87 @@ public: /// implementation. /// /// \see lldb_private::TypeSystemClang::GetType(clang::QualType) - CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type) - : m_type(type), m_type_system(type_system) { + CompilerType(lldb::TypeSystemWP type_system, + lldb::opaque_compiler_type_t type) + : m_type_system(type_system), m_type(type) { + assert(Verify() && "verification failed"); + } + + /// This is a minimal wrapper of a TypeSystem shared pointer as + /// returned by CompilerType which conventien dyn_cast support. + class TypeSystemSPWrapper { + lldb::TypeSystemSP m_typesystem_sp; + + public: + TypeSystemSPWrapper() = default; + TypeSystemSPWrapper(lldb::TypeSystemSP typesystem_sp) + : m_typesystem_sp(typesystem_sp) {} + + template bool isa_and_nonnull() { + if (auto *ts = m_typesystem_sp.get()) + return llvm::isa(ts); + return false; + } + + /// Return a shared_ptr if dyn_cast succeeds. + template + std::shared_ptr dyn_cast_or_null() { + if (isa_and_nonnull()) + return std::shared_ptr( + m_typesystem_sp, llvm::cast(m_typesystem_sp.get())); + return nullptr; + } + + explicit operator bool() const { + return static_cast(m_typesystem_sp); + } + bool operator==(const TypeSystemSPWrapper &other) const; + bool operator!=(const TypeSystemSPWrapper &other) const { + return !(*this == other); + } + + /// Only to be used in a one-off situations like + /// if (typesystem && typesystem->method()) + /// Do not store this pointer! + TypeSystem *operator->() const; + + lldb::TypeSystemSP GetSharedPointer() const { return m_typesystem_sp; } + }; + + CompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type) + : m_type_system(type_system.GetSharedPointer()), m_type(type) { assert(Verify() && "verification failed"); } CompilerType(const CompilerType &rhs) - : m_type(rhs.m_type), m_type_system(rhs.m_type_system) {} + : m_type_system(rhs.m_type_system), m_type(rhs.m_type) {} CompilerType() = default; /// Operators. /// \{ const CompilerType &operator=(const CompilerType &rhs) { - m_type = rhs.m_type; m_type_system = rhs.m_type_system; + m_type = rhs.m_type; return *this; } bool operator<(const CompilerType &rhs) const { - if (m_type_system == rhs.m_type_system) + auto lts = m_type_system.lock(); + auto rts = rhs.m_type_system.lock(); + if (lts.get() == rts.get()) return m_type < rhs.m_type; - return m_type_system < rhs.m_type_system; + return lts.get() < rts.get(); } /// \} /// Tests. /// \{ explicit operator bool() const { - return m_type != nullptr && m_type_system != nullptr; + return m_type_system.lock() && m_type; } - bool IsValid() const { return m_type != nullptr && m_type_system != nullptr; } + bool IsValid() const { return (bool)*this; } bool IsArrayType(CompilerType *element_type = nullptr, uint64_t *size = nullptr, @@ -142,6 +194,8 @@ public: bool IsScalarType() const; + bool IsTemplateType() const; + bool IsTypedefType() const; bool IsVoidType() const; @@ -152,6 +206,8 @@ public: bool GetCompleteType() const; /// \} + bool IsForcefullyCompleted() const; + /// AST related queries. /// \{ size_t GetPointerByteSize() const; @@ -159,9 +215,12 @@ public: /// Accessors. /// \{ - TypeSystem *GetTypeSystem() const { return m_type_system; } - ConstString GetTypeName() const; + /// Returns a shared pointer to the type system. The + /// TypeSystem::TypeSystemSPWrapper can be compared for equality. + TypeSystemSPWrapper GetTypeSystem() const; + + ConstString GetTypeName(bool BaseOnly = false) const; ConstString GetDisplayTypeName() const; @@ -174,7 +233,9 @@ public: lldb::TypeClass GetTypeClass() const; - void SetCompilerType(TypeSystem *type_system, + void SetCompilerType(lldb::TypeSystemWP type_system, + lldb::opaque_compiler_type_t type); + void SetCompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type); unsigned GetTypeQualifiers() const; @@ -266,16 +327,15 @@ public: struct IntegralTemplateArgument; /// Return the size of the type in bytes. - llvm::Optional GetByteSize(ExecutionContextScope *exe_scope) const; + std::optional GetByteSize(ExecutionContextScope *exe_scope) const; /// Return the size of the type in bits. - llvm::Optional GetBitSize(ExecutionContextScope *exe_scope) const; + std::optional GetBitSize(ExecutionContextScope *exe_scope) const; lldb::Encoding GetEncoding(uint64_t &count) const; lldb::Format GetFormat() const; - llvm::Optional - GetTypeBitAlign(ExecutionContextScope *exe_scope) const; + std::optional GetTypeBitAlign(ExecutionContextScope *exe_scope) const; uint32_t GetNumChildren(bool omit_empty_base_classes, const ExecutionContext *exe_ctx) const; @@ -338,14 +398,28 @@ public: GetIndexOfChildMemberWithName(const char *name, bool omit_empty_base_classes, std::vector &child_indexes) const; - size_t GetNumTemplateArguments() const; - - lldb::TemplateArgumentKind GetTemplateArgumentKind(size_t idx) const; - CompilerType GetTypeTemplateArgument(size_t idx) const; + /// Return the number of template arguments the type has. + /// If expand_pack is true, then variadic argument packs are automatically + /// expanded to their supplied arguments. If it is false an argument pack + /// will only count as 1 argument. + size_t GetNumTemplateArguments(bool expand_pack = false) const; + + // Return the TemplateArgumentKind of the template argument at index idx. + // If expand_pack is true, then variadic argument packs are automatically + // expanded to their supplied arguments. With expand_pack set to false, an + // arguement pack will count as 1 argument and return a type of Pack. + lldb::TemplateArgumentKind + GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const; + CompilerType GetTypeTemplateArgument(size_t idx, + bool expand_pack = false) const; /// Returns the value of the template argument and its type. - llvm::Optional - GetIntegralTemplateArgument(size_t idx) const; + /// If expand_pack is true, then variadic argument packs are automatically + /// expanded to their supplied arguments. With expand_pack set to false, an + /// arguement pack will count as 1 argument and it is invalid to call this + /// method on the pack argument. + std::optional + GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; CompilerType GetTypeForFormatters() const; @@ -393,8 +467,8 @@ public: size_t data_byte_size, Scalar &value, ExecutionContextScope *exe_scope) const; void Clear() { + m_type_system = {}; m_type = nullptr; - m_type_system = nullptr; } private: @@ -405,8 +479,8 @@ private: bool Verify() const; #endif + lldb::TypeSystemWP m_type_system; lldb::opaque_compiler_type_t m_type = nullptr; - TypeSystem *m_type_system = nullptr; }; bool operator==(const CompilerType &lhs, const CompilerType &rhs); diff --git a/gnu/llvm/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/gnu/llvm/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h index f85bc7e844a..ea5c325e11a 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -11,6 +11,7 @@ #include #include +#include #include "lldb/Core/AddressRange.h" #include "lldb/Core/dwarf.h" @@ -106,8 +107,9 @@ private: CIE(dw_offset_t offset) : cie_offset(offset), version(-1), code_align(0), data_align(0), return_addr_reg_num(LLDB_INVALID_REGNUM), inst_offset(0), - inst_length(0), ptr_encoding(0), lsda_addr_encoding(DW_EH_PE_omit), - personality_loc(LLDB_INVALID_ADDRESS), initial_row() {} + inst_length(0), ptr_encoding(0), + lsda_addr_encoding(llvm::dwarf::DW_EH_PE_omit), + personality_loc(LLDB_INVALID_ADDRESS) {} }; typedef std::shared_ptr CIESP; @@ -121,7 +123,7 @@ private: bool IsEHFrame() const; - llvm::Optional + std::optional GetFirstFDEEntryInRange(const AddressRange &range); void GetFDEIndex(); diff --git a/gnu/llvm/lldb/include/lldb/Symbol/DebugMacros.h b/gnu/llvm/lldb/include/lldb/Symbol/DebugMacros.h index 0ea70f5deb8..fbc5be0ee60 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/DebugMacros.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/DebugMacros.h @@ -39,7 +39,7 @@ public: static DebugMacroEntry CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp); - DebugMacroEntry() : m_type(INVALID) {} + DebugMacroEntry() : m_type(INVALID), m_line(0), m_debug_line_file_idx(0) {} ~DebugMacroEntry() = default; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Function.h b/gnu/llvm/lldb/include/lldb/Symbol/Function.h index b703617773f..2da13f878a7 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Function.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Function.h @@ -12,7 +12,7 @@ #include "lldb/Core/AddressRange.h" #include "lldb/Core/Declaration.h" #include "lldb/Core/Mangled.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Symbol/Block.h" #include "lldb/Utility/UserID.h" #include "llvm/ADT/ArrayRef.h" @@ -110,8 +110,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () virtual size_t MemorySize() const; protected: @@ -238,8 +236,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const override; private: @@ -257,8 +253,8 @@ class Function; /// Represent the locations of a parameter at a call site, both in the caller /// and in the callee. struct CallSiteParameter { - DWARFExpression LocationInCallee; - DWARFExpression LocationInCaller; + DWARFExpressionList LocationInCallee; + DWARFExpressionList LocationInCaller; }; /// A vector of \c CallSiteParameter. @@ -374,7 +370,7 @@ class IndirectCallEdge : public CallEdge { public: /// Construct a call edge using a DWARFExpression to identify the callee, and /// a return PC within the calling function to identify a specific call site. - IndirectCallEdge(DWARFExpression call_target, AddrType caller_address_type, + IndirectCallEdge(DWARFExpressionList call_target, AddrType caller_address_type, lldb::addr_t caller_address, bool is_tail_call, CallSiteParameterArray &¶meters) : CallEdge(caller_address_type, caller_address, is_tail_call, @@ -387,7 +383,7 @@ private: // Used to describe an indirect call. // // Specifies the location of the callee address in the calling frame. - DWARFExpression call_target; + DWARFExpressionList call_target; }; /// \class Function Function.h "lldb/Symbol/Function.h" @@ -489,7 +485,7 @@ public: llvm::ArrayRef> GetCallEdges(); /// Get the outgoing tail-calling edges from this function. If none exist, - /// return None. + /// return std::nullopt. llvm::ArrayRef> GetTailCallingEdges(); /// Get the outgoing call edge from this function which has the given return @@ -525,13 +521,13 @@ public: /// \return /// A location expression that describes the function frame /// base. - DWARFExpression &GetFrameBaseExpression() { return m_frame_base; } + DWARFExpressionList &GetFrameBaseExpression() { return m_frame_base; } /// Get const accessor for the frame base location. /// /// \return /// A const compile unit object pointer. - const DWARFExpression &GetFrameBaseExpression() const { return m_frame_base; } + const DWARFExpressionList &GetFrameBaseExpression() const { return m_frame_base; } ConstString GetName() const; @@ -595,8 +591,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Get whether compiler optimizations were enabled for this function @@ -665,7 +659,7 @@ protected: /// The frame base expression for variables that are relative to the frame /// pointer. - DWARFExpression m_frame_base; + DWARFExpressionList m_frame_base; Flags m_flags; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/LineTable.h b/gnu/llvm/lldb/include/lldb/Symbol/LineTable.h index 5cd22bd831e..7fca44b5930 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/LineTable.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/LineTable.h @@ -206,7 +206,6 @@ public: LineTable *LinkLineTable(const FileRangeMap &file_range_map); -protected: struct Entry { Entry() : line(0), is_start_of_statement(false), is_start_of_basic_block(false), @@ -303,6 +302,7 @@ protected: uint16_t file_idx = 0; }; +protected: struct EntrySearchInfo { LineTable *line_table; lldb_private::Section *a_section; @@ -350,9 +350,9 @@ private: if (!line_entry_ptr) return best_match; - const uint32_t line = src_location_spec.GetLine().getValueOr(0); + const uint32_t line = src_location_spec.GetLine().value_or(0); const uint16_t column = - src_location_spec.GetColumn().getValueOr(LLDB_INVALID_COLUMN_NUMBER); + src_location_spec.GetColumn().value_or(LLDB_INVALID_COLUMN_NUMBER); const bool exact_match = src_location_spec.GetExactMatch(); for (size_t idx = start_idx; idx < count; ++idx) { diff --git a/gnu/llvm/lldb/include/lldb/Symbol/LocateSymbolFile.h b/gnu/llvm/lldb/include/lldb/Symbol/LocateSymbolFile.h index 2c3f6a7b7b5..6f0506e671c 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/LocateSymbolFile.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/LocateSymbolFile.h @@ -13,6 +13,8 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-forward.h" namespace lldb_private { @@ -50,7 +52,16 @@ public: // enabled the external program before calling. // static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, - bool force_lookup = true); + Status &error, + bool force_lookup = true, + bool copy_executable = true); + + /// Locate the symbol file for the given UUID on a background thread. This + /// function returns immediately. Under the hood it uses the debugger's + /// thread pool to call DownloadObjectAndSymbolFile. If a symbol file is + /// found, this will notify all target which contain the module with the + /// given UUID. + static void DownloadSymbolFileAsync(const UUID &uuid); }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Symbol/ObjectContainer.h b/gnu/llvm/lldb/include/lldb/Symbol/ObjectContainer.h index 1e01e93da9d..cd4713b271c 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/ObjectContainer.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/ObjectContainer.h @@ -36,15 +36,7 @@ public: /// more than one architecture or object. ObjectContainer(const lldb::ModuleSP &module_sp, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length, - lldb::DataBufferSP &data_sp, lldb::offset_t data_offset) - : ModuleChild(module_sp), - m_file(), // This file can be different than the module's file spec - m_offset(file_offset), m_length(length), m_data() { - if (file) - m_file = *file; - if (data_sp) - m_data.SetData(data_sp, data_offset, length); - } + lldb::DataBufferSP data_sp, lldb::offset_t data_offset); /// Destructor. /// @@ -52,16 +44,6 @@ public: /// from by the plug-in instance. ~ObjectContainer() override = default; - /// Dump a description of this object to a Stream. - /// - /// Dump a description of the current contents of this object to the - /// supplied stream \a s. The dumping should include the section list if it - /// has been parsed, and the symbol table if it has been parsed. - /// - /// \param[in] s - /// The stream to which to dump the object description. - virtual void Dump(Stream *s) const = 0; - /// Gets the architecture given an index. /// /// Copies the architecture specification for index \a idx. @@ -142,29 +124,23 @@ public: /// file exists in the container. virtual lldb::ObjectFileSP GetObjectFile(const FileSpec *file) = 0; - virtual bool ObjectAtIndexIsContainer(uint32_t object_idx) { return false; } + static lldb::ObjectContainerSP + FindPlugin(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, lldb::WritableDataBufferSP file_data_sp); - virtual ObjectFile *GetObjectFileAtIndex(uint32_t object_idx) { - return nullptr; - } +protected: + /// The file that represents this container objects (which can be different + /// from the module's file). + FileSpec m_file; - virtual ObjectContainer *GetObjectContainerAtIndex(uint32_t object_idx) { - return nullptr; - } + /// The offset in bytes into the file, or the address in memory + lldb::addr_t m_offset; - virtual const char *GetObjectNameAtIndex(uint32_t object_idx) const { - return nullptr; - } + /// The size in bytes if known (can be zero). + lldb::addr_t m_length; -protected: - // Member variables. - FileSpec m_file; ///< The file that represents this container objects (which - ///can be different from the module's file). - lldb::addr_t - m_offset; ///< The offset in bytes into the file, or the address in memory - lldb::addr_t m_length; ///< The size in bytes if known (can be zero). - DataExtractor - m_data; ///< The data for this object file so things can be parsed lazily. + /// The data for this object file so things can be parsed lazily. + DataExtractor m_data; private: ObjectContainer(const ObjectContainer &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/ObjectFile.h b/gnu/llvm/lldb/include/lldb/Symbol/ObjectFile.h index 4ccd7f92064..e2e0623c9f9 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/ObjectFile.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/ObjectFile.h @@ -19,7 +19,9 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/VersionTuple.h" +#include namespace lldb_private { @@ -114,10 +116,10 @@ public: /// more than one architecture or object. ObjectFile(const lldb::ModuleSP &module_sp, const FileSpec *file_spec_ptr, lldb::offset_t file_offset, lldb::offset_t length, - const lldb::DataBufferSP &data_sp, lldb::offset_t data_offset); + lldb::DataBufferSP data_sp, lldb::offset_t data_offset); ObjectFile(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, - lldb::addr_t header_addr, lldb::DataBufferSP &data_sp); + lldb::addr_t header_addr, lldb::DataBufferSP data_sp); /// Destructor. /// @@ -181,7 +183,7 @@ public: static lldb::ObjectFileSP FindPlugin(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, - lldb::DataBufferSP &file_data_sp); + lldb::WritableDataBufferSP file_data_sp); static size_t GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset, @@ -322,12 +324,26 @@ public: /// Gets the symbol table for the currently selected architecture (and /// object for archives). /// - /// Symbol table parsing can be deferred by ObjectFile instances until this - /// accessor is called the first time. + /// This function will manage when ParseSymtab(...) is called to actually do + /// the symbol table parsing in each plug-in. This function will take care of + /// taking all the necessary locks and finalizing the symbol table when the + /// symbol table does get parsed. /// /// \return /// The symbol table for this object file. - virtual Symtab *GetSymtab() = 0; + Symtab *GetSymtab(); + + /// Parse the symbol table into the provides symbol table object. + /// + /// Symbol table parsing will be done once when this function is called by + /// each object file plugin. All of the necessary locks will already be + /// acquired before this function is called and the symbol table object to + /// populate is supplied as an argument and doesn't need to be created by + /// each plug-in. + /// + /// \param + /// The symbol table to populate. + virtual void ParseSymtab(Symtab &symtab) = 0; /// Perform relocations on the section if necessary. /// @@ -511,11 +527,15 @@ public: /// binary is exactly which removes ambiguity when there are multiple /// binaries present in the captured memory pages. /// - /// \param[out] address - /// If the address of the binary is specified, this will be set. - /// This is an address is the virtual address space of the core file - /// memory segments; it is not an offset into the object file. - /// If no address is available, will be set to LLDB_INVALID_ADDRESS. + /// \param[out] value + /// The address or offset (slide) where the binary is loaded in memory. + /// LLDB_INVALID_ADDRESS for unspecified. If an offset is given, + /// this offset should be added to the binary's file address to get + /// the load address. + /// + /// \param[out] value_is_offset + /// Specifies if \b value is a load address, or an offset to calculate + /// the load address. /// /// \param[out] uuid /// If the uuid of the binary is specified, this will be set. @@ -527,9 +547,11 @@ public: /// /// \return /// Returns true if either address or uuid has been set. - virtual bool GetCorefileMainBinaryInfo(lldb::addr_t &address, UUID &uuid, + virtual bool GetCorefileMainBinaryInfo(lldb::addr_t &value, + bool &value_is_offset, UUID &uuid, ObjectFile::BinaryType &type) { - address = LLDB_INVALID_ADDRESS; + value = LLDB_INVALID_ADDRESS; + value_is_offset = false; uuid.Clear(); return false; } @@ -651,6 +673,7 @@ public: virtual size_t ReadSectionData(Section *section, DataExtractor §ion_data); + /// Returns true if the object file exists only in memory. bool IsInMemory() const { return m_memory_addr != LLDB_INVALID_ADDRESS; } // Strip linker annotations (such as @@VERSION) from symbol names. @@ -659,6 +682,10 @@ public: return symbol_name; } + /// Can we trust the address ranges accelerator associated with this object + /// file to be complete. + virtual bool CanTrustAddressRanges() { return false; } + static lldb::SymbolType GetSymbolTypeFromName( llvm::StringRef name, lldb::SymbolType symbol_type_hint = lldb::eSymbolTypeUndefined); @@ -692,6 +719,17 @@ public: return false; } + /// Get a hash that can be used for caching object file releated information. + /// + /// Data for object files can be cached between runs of debug sessions and + /// a module can end up using a main file and a symbol file, both of which + /// can be object files. So we need a unique hash that identifies an object + /// file when storing cached data. + uint32_t GetCacheHash(); + + static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, + uint64_t Offset); + protected: // Member variables. FileSpec m_file; @@ -705,10 +743,17 @@ protected: DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. lldb::ProcessWP m_process_wp; + /// Set if the object file only exists in memory. const lldb::addr_t m_memory_addr; std::unique_ptr m_sections_up; std::unique_ptr m_symtab_up; - uint32_t m_synthetic_symbol_idx; + /// We need a llvm::once_flag that we can use to avoid locking the module + /// lock and deadlocking LLDB. See comments in ObjectFile::GetSymtab() for + /// the full details. We also need to be able to clear the symbol table, so we + /// need to use a std::unique_ptr to a llvm::once_flag so if we clear the + /// symbol table, we can have a new once flag to use when it is created again. + std::unique_ptr m_symtab_once_up; + std::optional m_cache_hash; /// Sets the architecture for a module. At present the architecture can /// only be set if it is invalid. It is not allowed to switch from one @@ -722,8 +767,8 @@ protected: /// false otherwise. bool SetModulesArchitecture(const ArchSpec &new_arch); - static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, - uint64_t Offset); + /// The number of bytes to read when going through the plugins. + static size_t g_initial_bytes_to_read; private: ObjectFile(const ObjectFile &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Symbol.h b/gnu/llvm/lldb/include/lldb/Symbol/Symbol.h index cb238546870..164fafd437d 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Symbol.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Symbol.h @@ -85,6 +85,16 @@ public: return Address(); } + /// Get the raw value of the symbol from the symbol table. + /// + /// If the symbol's value is an address, return the file address, else return + /// the raw value that is stored in the m_addr_range. If the base address has + /// no section, then getting the file address will return the correct value + /// as it will return the offset in the base address which is the value. + uint64_t GetRawValue() const { + return m_addr_range.GetBaseAddress().GetFileAddress(); + } + // When a symbol's value isn't an address, we need to access the raw value. // This function will ensure this symbol's value isn't an address and return // the integer value if this checks out, otherwise it will return @@ -235,6 +245,46 @@ public: return "___lldb_unnamed_symbol"; } + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \param section_list + /// A section list that allows lldb_private::Address objects to be filled + /// in. The address information for symbols are serilized as file addresses + /// and must be converted into Address objects with the right section and + /// offset. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + /// + /// \return + /// True if the symbol is successfully decoded, false otherwise. + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + const SectionList *section_list, const StringTableReader &strtab); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \param strtab + /// All strings in cache files are put into string tables for efficiency + /// and cache file size reduction. Strings are stored as uint32_t string + /// table offsets in the cache data. + void Encode(DataEncoder &encoder, ConstStringTable &strtab) const; + + bool operator==(const Symbol &rhs) const; + protected: // This is the internal guts of ResolveReExportedSymbol, it assumes // reexport_name is not null, and that module_spec is valid. We track the diff --git a/gnu/llvm/lldb/include/lldb/Symbol/SymbolFile.h b/gnu/llvm/lldb/include/lldb/Symbol/SymbolFile.h index ffdbdc6853f..8548973bad3 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/SymbolFile.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/SymbolFile.h @@ -9,6 +9,8 @@ #ifndef LLDB_SYMBOL_SYMBOLFILE_H #define LLDB_SYMBOL_SYMBOLFILE_H +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/SourceLocationSpec.h" #include "lldb/Symbol/CompilerDecl.h" @@ -19,12 +21,14 @@ #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/Statistics.h" #include "lldb/Utility/XcodeSDK.h" #include "lldb/lldb-private.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/Errc.h" #include +#include #if defined(LLDB_CONFIGURATION_DEBUG) #define ASSERT_MODULE_LOCK(expr) (expr->AssertModuleLock()) @@ -34,6 +38,12 @@ namespace lldb_private { +/// Provides public interface for all SymbolFiles. Any protected +/// virtual members should go into SymbolFileCommon; most SymbolFile +/// implementations should inherit from SymbolFileCommon to override +/// the behaviors except SymbolFileOnDemand which inherits +/// public interfaces from SymbolFile and forward to underlying concrete +/// SymbolFile implementation. class SymbolFile : public PluginInterface { /// LLVM RTTI support. static char ID; @@ -65,12 +75,14 @@ public: static SymbolFile *FindPlugin(lldb::ObjectFileSP objfile_sp); // Constructors and Destructors - SymbolFile(lldb::ObjectFileSP objfile_sp) - : m_objfile_sp(std::move(objfile_sp)), m_abilities(0), - m_calculated_abilities(false) {} + SymbolFile() = default; ~SymbolFile() override = default; + /// SymbolFileOnDemand class overrides this to return the underlying + /// backing SymbolFile implementation that loads on-demand. + virtual SymbolFile *GetBackingSymbolFile() { return this; } + /// Get a mask of what this symbol file supports for the object file /// that it was constructed with. /// @@ -98,15 +110,7 @@ public: /// A uint32_t mask containing bits from the SymbolFile::Abilities /// enumeration. Any bits that are set represent an ability that /// this symbol plug-in can parse from the object file. - uint32_t GetAbilities() { - if (!m_calculated_abilities) { - m_abilities = CalculateAbilities(); - m_calculated_abilities = true; - } - - return m_abilities; - } - + virtual uint32_t GetAbilities() = 0; virtual uint32_t CalculateAbilities() = 0; /// Symbols file subclasses should override this to return the Module that @@ -122,12 +126,22 @@ public: /// prior to any other functions in the SymbolFile protocol. virtual void InitializeObject() {} + /// Whether debug info will be loaded or not. + /// + /// It will be true for most implementations except SymbolFileOnDemand. + virtual bool GetLoadDebugInfoEnabled() { return true; } + + /// Specify debug info should be loaded. + /// + /// It will be no-op for most implementations except SymbolFileOnDemand. + virtual void SetLoadDebugInfoEnabled() {} + // Compile Unit function calls // Approach 1 - iterator - uint32_t GetNumCompileUnits(); - lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx); + virtual uint32_t GetNumCompileUnits() = 0; + virtual lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) = 0; - Symtab *GetSymtab(); + virtual Symtab *GetSymtab() = 0; virtual lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) = 0; /// Return the Xcode SDK comp_unit was compiled against. @@ -180,7 +194,6 @@ public: virtual size_t ParseVariablesForContext(const SymbolContext &sc) = 0; virtual Type *ResolveTypeUID(lldb::user_id_t type_uid) = 0; - /// The characteristics of an array type. struct ArrayInfo { int64_t first_index = 0; @@ -192,7 +205,7 @@ public: /// To support variable-length array types, this function takes an /// optional \p ExecutionContext. If \c exe_ctx is non-null, the /// dynamic characteristics for that context are returned. - virtual llvm::Optional + virtual std::optional GetDynamicArrayInfoForUID(lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) = 0; @@ -210,6 +223,50 @@ public: virtual uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) = 0; + + /// Get an error that describes why variables might be missing for a given + /// symbol context. + /// + /// If there is an error in the debug information that prevents variables from + /// being fetched, this error will get filled in. If there is no debug + /// informaiton, no error should be returned. But if there is debug + /// information and something prevents the variables from being available a + /// valid error should be returned. Valid cases include: + /// - compiler option that removes variables (-gline-tables-only) + /// - missing external files + /// - .dwo files in fission are not accessible or missing + /// - .o files on darwin when not using dSYM files that are not accessible + /// or missing + /// - mismatched exteral files + /// - .dwo files in fission where the DWO ID doesn't match + /// - .o files on darwin when modification timestamp doesn't match + /// - corrupted debug info + /// + /// \param[in] frame + /// The stack frame to use as a basis for the context to check. The frame + /// address can be used if there is not debug info due to it not being able + /// to be loaded, or if there is a debug info context, like a compile unit, + /// or function, it can be used to track down more information on why + /// variables are missing. + /// + /// \returns + /// An error specifying why there should have been debug info with variable + /// information but the variables were not able to be resolved. + Status GetFrameVariableError(StackFrame &frame) { + Status err = CalculateFrameVariableError(frame); + if (err.Fail()) + SetDebugInfoHadFrameVariableErrors(); + return err; + } + + /// Subclasses will override this function to for GetFrameVariableError(). + /// + /// This allows GetFrameVariableError() to set the member variable + /// m_debug_info_had_variable_errors correctly without users having to do it + /// manually which is error prone. + virtual Status CalculateFrameVariableError(StackFrame &frame) { + return Status(); + } virtual uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, @@ -223,9 +280,8 @@ public: virtual void FindGlobalVariables(const RegularExpression ®ex, uint32_t max_matches, VariableList &variables); - virtual void FindFunctions(ConstString name, + virtual void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, - lldb::FunctionNameType name_type_mask, bool include_inlines, SymbolContextList &sc_list); virtual void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list); @@ -255,17 +311,17 @@ public: virtual void PreloadSymbols(); - virtual llvm::Expected - GetTypeSystemForLanguage(lldb::LanguageType language); + virtual llvm::Expected + GetTypeSystemForLanguage(lldb::LanguageType language) = 0; virtual CompilerDeclContext FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx) { return CompilerDeclContext(); } - ObjectFile *GetObjectFile() { return m_objfile_sp.get(); } - const ObjectFile *GetObjectFile() const { return m_objfile_sp.get(); } - ObjectFile *GetMainObjectFile(); + virtual ObjectFile *GetObjectFile() = 0; + virtual const ObjectFile *GetObjectFile() const = 0; + virtual ObjectFile *GetMainObjectFile() = 0; virtual std::vector> ParseCallEdgesInFunction(UserID func_id) { @@ -276,7 +332,7 @@ public: /// Notify the SymbolFile that the file addresses in the Sections /// for this module have been changed. - virtual void SectionFileAddressesChanged(); + virtual void SectionFileAddressesChanged() = 0; struct RegisterInfoResolver { virtual ~RegisterInfoResolver(); // anchor @@ -297,29 +353,213 @@ public: "Operation not supported."); } - virtual void Dump(Stream &s); + virtual void Dump(Stream &s) = 0; + + /// Metrics gathering functions + + /// Return the size in bytes of all debug information in the symbol file. + /// + /// If the debug information is contained in sections of an ObjectFile, then + /// this call should add the size of all sections that contain debug + /// information. Symbols the symbol tables are not considered debug + /// information for this call to make it easy and quick for this number to be + /// calculated. If the symbol file is all debug information, the size of the + /// entire file should be returned. The default implementation of this + /// function will iterate over all sections in a module and add up their + /// debug info only section byte sizes. + virtual uint64_t GetDebugInfoSize() = 0; + + /// Return the time taken to parse the debug information. + /// + /// \returns 0.0 if no information has been parsed or if there is + /// no computational cost to parsing the debug information. + virtual StatsDuration::Duration GetDebugInfoParseTime() { return {}; } + + /// Return the time it took to index the debug information in the object + /// file. + /// + /// \returns 0.0 if the file doesn't need to be indexed or if it + /// hasn't been indexed yet, or a valid duration if it has. + virtual StatsDuration::Duration GetDebugInfoIndexTime() { return {}; } + + /// Get the additional modules that this symbol file uses to parse debug info. + /// + /// Some debug info is stored in stand alone object files that are represented + /// by unique modules that will show up in the statistics module list. Return + /// a list of modules that are not in the target module list that this symbol + /// file is currently using so that they can be tracked and assoicated with + /// the module in the statistics. + virtual ModuleList GetDebugInfoModules() { return ModuleList(); } + + /// Accessors for the bool that indicates if the debug info index was loaded + /// from, or saved to the module index cache. + /// + /// In statistics it is handy to know if a module's debug info was loaded from + /// or saved to the cache. When the debug info index is loaded from the cache + /// startup times can be faster. When the cache is enabled and the debug info + /// index is saved to the cache, debug sessions can be slower. These accessors + /// can be accessed by the statistics and emitted to help track these costs. + /// \{ + virtual bool GetDebugInfoIndexWasLoadedFromCache() const = 0; + virtual void SetDebugInfoIndexWasLoadedFromCache() = 0; + virtual bool GetDebugInfoIndexWasSavedToCache() const = 0; + virtual void SetDebugInfoIndexWasSavedToCache() = 0; + /// \} + + /// Accessors for the bool that indicates if there was debug info, but errors + /// stopped variables from being able to be displayed correctly. See + /// GetFrameVariableError() for details on what are considered errors. + virtual bool GetDebugInfoHadFrameVariableErrors() const = 0; + virtual void SetDebugInfoHadFrameVariableErrors() = 0; + + virtual lldb::TypeSP + MakeType(lldb::user_id_t uid, ConstString name, + std::optional byte_size, SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) = 0; + + virtual lldb::TypeSP CopyType(const lldb::TypeSP &other_type) = 0; protected: void AssertModuleLock(); + +private: + SymbolFile(const SymbolFile &) = delete; + const SymbolFile &operator=(const SymbolFile &) = delete; +}; + +/// Containing protected virtual methods for child classes to override. +/// Most actual SymbolFile implementations should inherit from this class. +class SymbolFileCommon : public SymbolFile { + /// LLVM RTTI support. + static char ID; + +public: + /// LLVM RTTI support. + /// \{ + bool isA(const void *ClassID) const override { + return ClassID == &ID || SymbolFile::isA(ClassID); + } + static bool classof(const SymbolFileCommon *obj) { return obj->isA(&ID); } + /// \} + + // Constructors and Destructors + SymbolFileCommon(lldb::ObjectFileSP objfile_sp) + : m_objfile_sp(std::move(objfile_sp)) {} + + ~SymbolFileCommon() override = default; + + uint32_t GetAbilities() override { + if (!m_calculated_abilities) { + m_abilities = CalculateAbilities(); + m_calculated_abilities = true; + } + return m_abilities; + } + + Symtab *GetSymtab() override; + + ObjectFile *GetObjectFile() override { return m_objfile_sp.get(); } + const ObjectFile *GetObjectFile() const override { + return m_objfile_sp.get(); + } + ObjectFile *GetMainObjectFile() override; + + /// Notify the SymbolFile that the file addresses in the Sections + /// for this module have been changed. + void SectionFileAddressesChanged() override; + + // Compile Unit function calls + // Approach 1 - iterator + uint32_t GetNumCompileUnits() override; + lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override; + + llvm::Expected + GetTypeSystemForLanguage(lldb::LanguageType language) override; + + void Dump(Stream &s) override; + + uint64_t GetDebugInfoSize() override; + + bool GetDebugInfoIndexWasLoadedFromCache() const override { + return m_index_was_loaded_from_cache; + } + void SetDebugInfoIndexWasLoadedFromCache() override { + m_index_was_loaded_from_cache = true; + } + bool GetDebugInfoIndexWasSavedToCache() const override { + return m_index_was_saved_to_cache; + } + void SetDebugInfoIndexWasSavedToCache() override { + m_index_was_saved_to_cache = true; + } + bool GetDebugInfoHadFrameVariableErrors() const override { + return m_debug_info_had_variable_errors; + } + void SetDebugInfoHadFrameVariableErrors() override { + m_debug_info_had_variable_errors = true; + } + + /// This function is used to create types that belong to a SymbolFile. The + /// symbol file will own a strong reference to the type in an internal type + /// list. + lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, + std::optional byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, + const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) override { + lldb::TypeSP type_sp (new Type( + uid, this, name, byte_size, context, encoding_uid, + encoding_uid_type, decl, compiler_qual_type, + compiler_type_resolve_state, opaque_payload)); + m_type_list.Insert(type_sp); + return type_sp; + } + + lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { + // Make sure the real symbol file matches when copying types. + if (GetBackingSymbolFile() != other_type->GetSymbolFile()) + return lldb::TypeSP(); + lldb::TypeSP type_sp(new Type(*other_type)); + m_type_list.Insert(type_sp); + return type_sp; + } + +protected: virtual uint32_t CalculateNumCompileUnits() = 0; virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t idx) = 0; virtual TypeList &GetTypeList() { return m_type_list; } - void SetCompileUnitAtIndex(uint32_t idx, const lldb::CompUnitSP &cu_sp); lldb::ObjectFileSP m_objfile_sp; // Keep a reference to the object file in // case it isn't the same as the module // object file (debug symbols in a separate // file) - llvm::Optional> m_compile_units; + std::optional> m_compile_units; TypeList m_type_list; - Symtab *m_symtab = nullptr; - uint32_t m_abilities; - bool m_calculated_abilities; + uint32_t m_abilities = 0; + bool m_calculated_abilities = false; + bool m_index_was_loaded_from_cache = false; + bool m_index_was_saved_to_cache = false; + /// Set to true if any variable feteching errors have been found when calling + /// GetFrameVariableError(). This will be emitted in the "statistics dump" + /// information for a module. + bool m_debug_info_had_variable_errors = false; private: - SymbolFile(const SymbolFile &) = delete; - const SymbolFile &operator=(const SymbolFile &) = delete; + SymbolFileCommon(const SymbolFileCommon &) = delete; + const SymbolFileCommon &operator=(const SymbolFileCommon &) = delete; + + /// Do not use m_symtab directly, as it may be freed. Use GetSymtab() + /// to access it instead. + Symtab *m_symtab = nullptr; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/gnu/llvm/lldb/include/lldb/Symbol/SymbolFileOnDemand.h new file mode 100644 index 00000000000..825fba755e9 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Symbol/SymbolFileOnDemand.h @@ -0,0 +1,262 @@ +//===-- SymbolFileOnDemand.h ------------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SYMBOL_SYMBOLFILEONDEMAND_H +#define LLDB_SYMBOL_SYMBOLFILEONDEMAND_H + +#include +#include +#include + +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Target/Statistics.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +/// SymbolFileOnDemand wraps an actual SymbolFile by providing +/// on demand symbol parsing/indexing to improve performance. +/// By default SymbolFileOnDemand will skip load the underlying +/// symbols. Any client can on demand hydrate the underlying +/// SymbolFile via SymbolFile::SetLoadDebugInfoEnabled(). +class SymbolFileOnDemand : public lldb_private::SymbolFile { + /// LLVM RTTI support. + static char ID; + +public: + /// LLVM RTTI support. + /// \{ + bool isA(const void *ClassID) const override { + return ClassID == &ID || SymbolFile::isA(ClassID); + } + static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } + /// \} + + SymbolFileOnDemand(std::unique_ptr &&symbol_file); + ~SymbolFileOnDemand() override; + + // PluginInterface protocol + llvm::StringRef GetPluginName() override { return "ondemand"; } + + bool GetLoadDebugInfoEnabled() override { return m_debug_info_enabled; } + + void SetLoadDebugInfoEnabled() override; + + uint32_t GetNumCompileUnits() override; + lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override; + + SymbolFile *GetBackingSymbolFile() override { return m_sym_file_impl.get(); } + + uint32_t CalculateAbilities() override; + + std::recursive_mutex &GetModuleMutex() const override; + + lldb::LanguageType + ParseLanguage(lldb_private::CompileUnit &comp_unit) override; + + lldb_private::XcodeSDK + ParseXcodeSDK(lldb_private::CompileUnit &comp_unit) override; + + void InitializeObject() override; + + size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; + + bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; + + bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; + + bool ForEachExternalModule( + lldb_private::CompileUnit &, llvm::DenseSet &, + llvm::function_ref) override; + + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, + lldb_private::FileSpecList &support_files) override; + + bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override; + + size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; + + bool ParseImportedModules( + const lldb_private::SymbolContext &sc, + std::vector &imported_modules) override; + + size_t ParseBlocksRecursive(lldb_private::Function &func) override; + + size_t + ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; + + lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + std::optional GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; + + bool CompleteType(lldb_private::CompilerType &compiler_type) override; + + lldb_private::CompilerDecl GetDeclForUID(lldb::user_id_t uid) override; + + lldb_private::CompilerDeclContext + GetDeclContextForUID(lldb::user_id_t uid) override; + + lldb_private::CompilerDeclContext + GetDeclContextContainingUID(lldb::user_id_t uid) override; + + void + ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; + + uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContext &sc) override; + + lldb_private::Status + CalculateFrameVariableError(lldb_private::StackFrame &frame) override; + + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; + + void Dump(lldb_private::Stream &s) override; + void DumpClangAST(lldb_private::Stream &s) override; + + void + FindGlobalVariables(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + uint32_t max_matches, + lldb_private::VariableList &variables) override; + + void FindGlobalVariables(const lldb_private::RegularExpression ®ex, + uint32_t max_matches, + lldb_private::VariableList &variables) override; + + void FindFunctions(const lldb_private::Module::LookupInfo &lookup_info, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + + void FindFunctions(const lldb_private::RegularExpression ®ex, + bool include_inlines, + lldb_private::SymbolContextList &sc_list) override; + + void GetMangledNamesForFunction( + const std::string &scope_qualified_name, + std::vector &mangled_names) override; + + void + FindTypes(lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx, + uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, + lldb_private::TypeMap &types) override; + + void FindTypes(llvm::ArrayRef pattern, + lldb_private::LanguageSet languages, + llvm::DenseSet &searched_symbol_files, + lldb_private::TypeMap &types) override; + + void GetTypes(lldb_private::SymbolContextScope *sc_scope, + lldb::TypeClass type_mask, + lldb_private::TypeList &type_list) override; + + llvm::Expected + GetTypeSystemForLanguage(lldb::LanguageType language) override; + + lldb_private::CompilerDeclContext FindNamespace( + lldb_private::ConstString name, + const lldb_private::CompilerDeclContext &parent_decl_ctx) override; + + std::vector> + ParseCallEdgesInFunction(UserID func_id) override; + + lldb::UnwindPlanSP + GetUnwindPlan(const Address &address, + const RegisterInfoResolver &resolver) override; + + llvm::Expected GetParameterStackSize(Symbol &symbol) override; + + void PreloadSymbols() override; + + uint64_t GetDebugInfoSize() override; + lldb_private::StatsDuration::Duration GetDebugInfoParseTime() override; + lldb_private::StatsDuration::Duration GetDebugInfoIndexTime() override; + + uint32_t GetAbilities() override; + + Symtab *GetSymtab() override { return m_sym_file_impl->GetSymtab(); } + + ObjectFile *GetObjectFile() override { + return m_sym_file_impl->GetObjectFile(); + } + const ObjectFile *GetObjectFile() const override { + return m_sym_file_impl->GetObjectFile(); + } + ObjectFile *GetMainObjectFile() override { + return m_sym_file_impl->GetMainObjectFile(); + } + + void SectionFileAddressesChanged() override { + return m_sym_file_impl->SectionFileAddressesChanged(); + } + + bool GetDebugInfoIndexWasLoadedFromCache() const override { + return m_sym_file_impl->GetDebugInfoIndexWasLoadedFromCache(); + } + void SetDebugInfoIndexWasLoadedFromCache() override { + m_sym_file_impl->SetDebugInfoIndexWasLoadedFromCache(); + } + bool GetDebugInfoIndexWasSavedToCache() const override { + return m_sym_file_impl->GetDebugInfoIndexWasSavedToCache(); + } + void SetDebugInfoIndexWasSavedToCache() override { + m_sym_file_impl->SetDebugInfoIndexWasSavedToCache(); + } + bool GetDebugInfoHadFrameVariableErrors() const override { + return m_sym_file_impl->GetDebugInfoHadFrameVariableErrors(); + } + void SetDebugInfoHadFrameVariableErrors() override { + return m_sym_file_impl->SetDebugInfoHadFrameVariableErrors(); + } + + lldb::TypeSP MakeType(lldb::user_id_t uid, ConstString name, + std::optional byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + Type::EncodingDataType encoding_uid_type, + const Declaration &decl, + const CompilerType &compiler_qual_type, + Type::ResolveState compiler_type_resolve_state, + uint32_t opaque_payload = 0) override { + return m_sym_file_impl->MakeType( + uid, name, byte_size, context, encoding_uid, encoding_uid_type, decl, + compiler_qual_type, compiler_type_resolve_state, opaque_payload); + } + + lldb::TypeSP CopyType(const lldb::TypeSP &other_type) override { + return m_sym_file_impl->CopyType(other_type); + } + +private: + Log *GetLog() const { return ::lldb_private::GetLog(LLDBLog::OnDemand); } + + ConstString GetSymbolFileName() { + return GetObjectFile()->GetFileSpec().GetFilename(); + } + +private: + bool m_debug_info_enabled = false; + bool m_preload_symbols = false; + std::unique_ptr m_sym_file_impl; +}; +} // namespace lldb_private + +#endif // LLDB_SYMBOL_SYMBOLFILEONDEMAND_H diff --git a/gnu/llvm/lldb/include/lldb/Symbol/SymbolVendor.h b/gnu/llvm/lldb/include/lldb/Symbol/SymbolVendor.h index 5c785e8c5a8..b060ac95b75 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/SymbolVendor.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/SymbolVendor.h @@ -41,9 +41,7 @@ public: SymbolFile *GetSymbolFile() { return m_sym_file_up.get(); } // PluginInterface protocol - ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; + llvm::StringRef GetPluginName() override { return "vendor-default"; } protected: std::unique_ptr m_sym_file_up; // A single symbol file. Subclasses diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Symtab.h b/gnu/llvm/lldb/include/lldb/Symbol/Symtab.h index e1ad0dfd2eb..57627d2dde7 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Symtab.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Symtab.h @@ -89,14 +89,16 @@ public: Debug symbol_debug_type, Visibility symbol_visibility, std::vector &matches); - uint32_t - AppendSymbolIndexesMatchingRegExAndType(const RegularExpression ®ex, - lldb::SymbolType symbol_type, - std::vector &indexes); + uint32_t AppendSymbolIndexesMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + std::vector &indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &indexes); + std::vector &indexes, + Mangled::NamePreference name_preference = + Mangled::NamePreference::ePreferDemangled); void FindAllSymbolsWithNameAndType(ConstString name, lldb::SymbolType symbol_type, std::vector &symbol_indexes); @@ -108,7 +110,8 @@ public: void FindAllSymbolsMatchingRexExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, - std::vector &symbol_indexes); + std::vector &symbol_indexes, + Mangled::NamePreference name_preference = Mangled::ePreferDemangled); Symbol *FindFirstSymbolWithNameAndType(ConstString name, lldb::SymbolType symbol_type, Debug symbol_debug_type, @@ -119,26 +122,122 @@ public: lldb::addr_t file_addr, std::function const &callback); void FindFunctionSymbols(ConstString name, uint32_t name_type_mask, SymbolContextList &sc_list); - void CalculateSymbolSizes(); void SortSymbolIndexesByValue(std::vector &indexes, bool remove_duplicates) const; static void DumpSymbolHeader(Stream *s); - void Finalize() { - // Shrink to fit the symbols so we don't waste memory - if (m_symbols.capacity() > m_symbols.size()) { - collection new_symbols(m_symbols.begin(), m_symbols.end()); - m_symbols.swap(new_symbols); - } - } + void Finalize(); void AppendSymbolNamesToMap(const IndexCollection &indexes, bool add_demangled, bool add_mangled, NameToIndexMap &name_to_index_map) const; - ObjectFile *GetObjectFile() { return m_objfile; } + ObjectFile *GetObjectFile() const { return m_objfile; } + + /// Decode a serialized version of this object from data. + /// + /// \param data + /// The decoder object that references the serialized data. + /// + /// \param offset_ptr + /// A pointer that contains the offset from which the data will be decoded + /// from that gets updated as data gets decoded. + /// + /// \param[out] uuid_mismatch + /// Set to true if a cache file exists but the UUID didn't match, false + /// otherwise. + /// + /// \return + /// True if the symbol table is successfully decoded and can be used, + /// false otherwise. + bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr, + bool &uuid_mismatch); + + /// Encode this object into a data encoder object. + /// + /// This allows this object to be serialized to disk. The object file must + /// have a valid Signature in order to be serialized as it is used to make + /// sure the cached information matches when cached data is loaded at a later + /// time. If the object file doesn't have a valid signature false will be + /// returned and it will indicate we should not cache this data. + /// + /// \param encoder + /// A data encoder object that serialized bytes will be encoded into. + /// + /// \return + /// True if the symbol table's object file can generate a valid signature + /// and all data for the symbol table was encoded, false otherwise. + bool Encode(DataEncoder &encoder) const; + + /// Get the cache key string for this symbol table. + /// + /// The cache key must start with the module's cache key and is followed + /// by information that indicates this key is for caching the symbol table + /// contents and should also include the has of the object file. A module can + /// be represented by an ObjectFile object for the main executable, but can + /// also have a symbol file that is from the same or a different object file. + /// This means we might have two symbol tables cached in the index cache, one + /// for the main executable and one for the symbol file. + /// + /// \return + /// The unique cache key used to save and retrieve data from the index cache. + std::string GetCacheKey(); + + /// Save the symbol table data out into a cache. + /// + /// The symbol table will only be saved to a cache file if caching is enabled. + /// + /// We cache the contents of the symbol table since symbol tables in LLDB take + /// some time to initialize. This is due to the many sources for data that are + /// used to create a symbol table: + /// - standard symbol table + /// - dynamic symbol table (ELF) + /// - compressed debug info sections + /// - unwind information + /// - function pointers found in runtimes for global constructor/destructors + /// - other sources. + /// All of the above sources are combined and one symbol table results after + /// all sources have been considered. + void SaveToCache(); + + /// Load the symbol table from the index cache. + /// + /// Quickly load the finalized symbol table from the index cache. This saves + /// time when the debugger starts up. The index cache file for the symbol + /// table has the modification time set to the same time as the main module. + /// If the cache file exists and the modification times match, we will load + /// the symbol table from the serlized cache file. + /// + /// \return + /// True if the symbol table was successfully loaded from the index cache, + /// false if the symbol table wasn't cached or was out of date. + bool LoadFromCache(); + + + /// Accessors for the bool that indicates if the debug info index was loaded + /// from, or saved to the module index cache. + /// + /// In statistics it is handy to know if a module's debug info was loaded from + /// or saved to the cache. When the debug info index is loaded from the cache + /// startup times can be faster. When the cache is enabled and the debug info + /// index is saved to the cache, debug sessions can be slower. These accessors + /// can be accessed by the statistics and emitted to help track these costs. + /// \{ + bool GetWasLoadedFromCache() const { + return m_loaded_from_cache; + } + void SetWasLoadedFromCache() { + m_loaded_from_cache = true; + } + bool GetWasSavedToCache() const { + return m_saved_to_cache; + } + void SetWasSavedToCache() { + m_saved_to_cache = true; + } + /// \} protected: typedef std::vector collection; @@ -180,7 +279,8 @@ protected: m_name_to_symbol_indices; mutable std::recursive_mutex m_mutex; // Provide thread safety for this symbol table - bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1; + bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1, + m_loaded_from_cache : 1, m_saved_to_cache : 1; private: UniqueCStringMap & diff --git a/gnu/llvm/lldb/include/lldb/Symbol/TaggedASTType.h b/gnu/llvm/lldb/include/lldb/Symbol/TaggedASTType.h index fe1a2c659d9..e46cf1b4742 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/TaggedASTType.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/TaggedASTType.h @@ -20,7 +20,8 @@ public: TaggedASTType(const CompilerType &compiler_type) : CompilerType(compiler_type) {} - TaggedASTType(lldb::opaque_compiler_type_t type, TypeSystem *type_system) + TaggedASTType(lldb::opaque_compiler_type_t type, + lldb::TypeSystemWP type_system) : CompilerType(type_system, type) {} TaggedASTType(const TaggedASTType &tw) : CompilerType(tw) {} diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Type.h b/gnu/llvm/lldb/include/lldb/Symbol/Type.h index 9e671a565dd..046501931d2 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Type.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Type.h @@ -18,9 +18,11 @@ #include "llvm/ADT/APSInt.h" +#include #include namespace lldb_private { +class SymbolFileCommon; /// CompilerContext allows an array of these items to be passed to perform /// detailed lookups in SymbolVendor and SymbolFile functions. @@ -66,24 +68,30 @@ protected: class Type : public std::enable_shared_from_this, public UserID { public: enum EncodingDataType { + /// Invalid encoding. eEncodingInvalid, - eEncodingIsUID, ///< This type is the type whose UID is m_encoding_uid - eEncodingIsConstUID, ///< This type is the type whose UID is m_encoding_uid - /// with the const qualifier added - eEncodingIsRestrictUID, ///< This type is the type whose UID is - /// m_encoding_uid with the restrict qualifier added - eEncodingIsVolatileUID, ///< This type is the type whose UID is - /// m_encoding_uid with the volatile qualifier added - eEncodingIsTypedefUID, ///< This type is pointer to a type whose UID is - /// m_encoding_uid - eEncodingIsPointerUID, ///< This type is pointer to a type whose UID is - /// m_encoding_uid - eEncodingIsLValueReferenceUID, ///< This type is L value reference to a type - /// whose UID is m_encoding_uid - eEncodingIsRValueReferenceUID, ///< This type is R value reference to a type - /// whose UID is m_encoding_uid, - eEncodingIsAtomicUID, ///< This type is the type whose UID is - /// m_encoding_uid as an atomic type. + /// This type is the type whose UID is m_encoding_uid. + eEncodingIsUID, + /// This type is the type whose UID is m_encoding_uid with the const + /// qualifier added. + eEncodingIsConstUID, + /// This type is the type whose UID is m_encoding_uid with the restrict + /// qualifier added. + eEncodingIsRestrictUID, + /// This type is the type whose UID is m_encoding_uid with the volatile + /// qualifier added. + eEncodingIsVolatileUID, + /// This type is alias to a type whose UID is m_encoding_uid. + eEncodingIsTypedefUID, + /// This type is pointer to a type whose UID is m_encoding_uid. + eEncodingIsPointerUID, + /// This type is L value reference to a type whose UID is m_encoding_uid. + eEncodingIsLValueReferenceUID, + /// This type is R value reference to a type whose UID is m_encoding_uid. + eEncodingIsRValueReferenceUID, + /// This type is the type whose UID is m_encoding_uid as an atomic type. + eEncodingIsAtomicUID, + /// This type is the synthetic type whose UID is m_encoding_uid. eEncodingIsSyntheticUID }; @@ -94,16 +102,6 @@ public: Full = 3 }; - Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, - llvm::Optional byte_size, SymbolContextScope *context, - lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, - const Declaration &decl, const CompilerType &compiler_qual_type, - ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0); - - // This makes an invalid type. Used for functions that return a Type when - // they get an error. - Type(); - void Dump(Stream *s, bool show_context, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); @@ -117,7 +115,7 @@ public: /// GetModule may return module for compile unit's object file. /// GetExeModule returns module for executable object file that contains - /// compile unit where type was actualy defined. + /// compile unit where type was actually defined. /// GetModule and GetExeModule may return the same value. lldb::ModuleSP GetExeModule(); @@ -129,12 +127,17 @@ public: ConstString GetName(); - llvm::Optional GetByteSize(ExecutionContextScope *exe_scope); + ConstString GetBaseName(); + + std::optional GetByteSize(ExecutionContextScope *exe_scope); uint32_t GetNumChildren(bool omit_empty_base_classes); bool IsAggregateType(); + // Returns if the type is a templated decl. Does not look through typedefs. + bool IsTemplateType(); + bool IsValidType() { return m_encoding_uid_type != eEncodingInvalid; } bool IsTypedef() { return m_encoding_uid_type == eEncodingIsTypedefUID; } @@ -160,14 +163,6 @@ public: bool WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t address, AddressType address_type, DataExtractor &data); - bool GetIsDeclaration() const; - - void SetIsDeclaration(bool b); - - bool GetIsExternal() const; - - void SetIsExternal(bool b); - lldb::Format GetFormat(); lldb::Encoding GetEncoding(uint64_t &count); @@ -197,7 +192,7 @@ public: // From a fully qualified typename, split the type into the type basename and // the remaining type scope (namespaces/classes). - static bool GetTypeScopeAndBasename(const llvm::StringRef& name, + static bool GetTypeScopeAndBasename(llvm::StringRef name, llvm::StringRef &scope, llvm::StringRef &basename, lldb::TypeClass &type_class); @@ -230,6 +225,30 @@ protected: Type *GetEncodingType(); bool ResolveCompilerType(ResolveState compiler_type_resolve_state); +private: + /// Only allow Symbol File to create types, as they should own them by keeping + /// them in their TypeList. \see SymbolFileCommon::MakeType() reference in the + /// header documentation here so users will know what function to use if the + /// get a compile error. + friend class lldb_private::SymbolFileCommon; + + Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, + std::optional byte_size, SymbolContextScope *context, + lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, + const Declaration &decl, const CompilerType &compiler_qual_type, + ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0); + + // This makes an invalid type. Used for functions that return a Type when + // they get an error. + Type(); + + Type(Type &t) = default; + + Type(Type &&t) = default; + + Type &operator=(const Type &t) = default; + + Type &operator=(Type &&t) = default; }; // the two classes here are used by the public API as a backend to the SBType @@ -289,7 +308,7 @@ public: CompilerType GetCompilerType(bool prefer_dynamic); - TypeSystem *GetTypeSystem(bool prefer_dynamic); + CompilerType::TypeSystemSPWrapper GetTypeSystem(bool prefer_dynamic); bool GetDescription(lldb_private::Stream &strm, lldb::DescriptionLevel description_level); @@ -308,7 +327,7 @@ private: class TypeListImpl { public: - TypeListImpl() : m_content() {} + TypeListImpl() = default; void Append(const lldb::TypeImplSP &type) { m_content.push_back(type); } @@ -339,10 +358,7 @@ private: class TypeMemberImpl { public: - TypeMemberImpl() - : m_type_impl_sp(), m_name() - - {} + TypeMemberImpl() = default; TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset, ConstString name, uint32_t bitfield_bit_size = 0, @@ -351,7 +367,7 @@ public: m_bitfield_bit_size(bitfield_bit_size), m_is_bitfield(is_bitfield) {} TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset) - : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_name(), + : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_bitfield_bit_size(0), m_is_bitfield(false) { if (m_type_impl_sp) m_name = m_type_impl_sp->GetName(); @@ -434,7 +450,7 @@ private: class TypeMemberFunctionImpl { public: - TypeMemberFunctionImpl() : m_type(), m_decl(), m_name() {} + TypeMemberFunctionImpl() = default; TypeMemberFunctionImpl(const CompilerType &type, const CompilerDecl &decl, const std::string &name, @@ -471,10 +487,10 @@ private: class TypeEnumMemberImpl { public: - TypeEnumMemberImpl() : m_integer_type_sp(), m_name(""), m_value() {} + TypeEnumMemberImpl() : m_name("") {} - TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, - ConstString name, const llvm::APSInt &value); + TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, ConstString name, + const llvm::APSInt &value); TypeEnumMemberImpl(const TypeEnumMemberImpl &rhs) = default; @@ -499,7 +515,7 @@ protected: class TypeEnumMemberListImpl { public: - TypeEnumMemberListImpl() : m_content() {} + TypeEnumMemberListImpl() = default; void Append(const lldb::TypeEnumMemberImplSP &type) { m_content.push_back(type); diff --git a/gnu/llvm/lldb/include/lldb/Symbol/TypeList.h b/gnu/llvm/lldb/include/lldb/Symbol/TypeList.h index 03390858025..403469c989f 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/TypeList.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/TypeList.h @@ -49,10 +49,11 @@ public: void ForEach(std::function const &callback); - void RemoveMismatchedTypes(const char *qualified_typename, bool exact_match); + void RemoveMismatchedTypes(llvm::StringRef qualified_typename, + bool exact_match); - void RemoveMismatchedTypes(const std::string &type_scope, - const std::string &type_basename, + void RemoveMismatchedTypes(llvm::StringRef type_scope, + llvm::StringRef type_basename, lldb::TypeClass type_class, bool exact_match); void RemoveMismatchedTypes(lldb::TypeClass type_class); diff --git a/gnu/llvm/lldb/include/lldb/Symbol/TypeMap.h b/gnu/llvm/lldb/include/lldb/Symbol/TypeMap.h index ede54c1a09d..c200ccb9844 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/TypeMap.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/TypeMap.h @@ -53,14 +53,10 @@ public: 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, + void RemoveMismatchedTypes(llvm::StringRef type_scope, + llvm::StringRef 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; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/TypeSystem.h b/gnu/llvm/lldb/include/lldb/Symbol/TypeSystem.h index a37c1040b16..a358d6fb13a 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/TypeSystem.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/TypeSystem.h @@ -10,15 +10,17 @@ #define LLDB_SYMBOL_TYPESYSTEM_H #include -#include #include +#include #include #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Expression/Expression.h" @@ -31,6 +33,9 @@ class DWARFASTParser; class PDBASTParser; namespace lldb_private { +namespace npdb { + class PdbAstBuilder; +} // namespace npdb /// A SmallBitVector that represents a set of source languages (\p /// lldb::LanguageType). Each lldb::LanguageType is represented by @@ -42,7 +47,7 @@ struct LanguageSet { LanguageSet(); /// If the set contains a single language only, return it. - llvm::Optional GetSingularLanguage(); + std::optional GetSingularLanguage(); void Insert(lldb::LanguageType language); bool Empty() const; size_t Size() const; @@ -68,7 +73,8 @@ struct LanguageSet { /// \see lldb_private::CompilerType /// \see lldb_private::CompilerDecl /// \see lldb_private::CompilerDeclContext -class TypeSystem : public PluginInterface { +class TypeSystem : public PluginInterface, + public std::enable_shared_from_this { public: // Constructors and Destructors ~TypeSystem() override; @@ -82,16 +88,16 @@ public: static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language, Target *target); - // Free up any resources associated with this TypeSystem. Done before - // removing all the TypeSystems from the TypeSystemMap. + /// Free up any resources associated with this TypeSystem. Done before + /// removing all the TypeSystems from the TypeSystemMap. virtual void Finalize() {} virtual DWARFASTParser *GetDWARFParser() { return nullptr; } virtual PDBASTParser *GetPDBParser() { return nullptr; } + virtual npdb::PdbAstBuilder *GetNativePDBParser() { 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 @@ -197,13 +203,18 @@ public: virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0; + virtual bool IsForcefullyCompleted(lldb::opaque_compiler_type_t type) { + return false; + } + // AST related queries virtual uint32_t GetPointerByteSize() = 0; // Accessors - virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type) = 0; + virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type, + bool BaseOnly) = 0; virtual ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) = 0; @@ -275,7 +286,7 @@ public: virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0; - virtual llvm::Optional + virtual std::optional GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0; @@ -347,14 +358,20 @@ public: const char *name, bool omit_empty_base_classes, std::vector &child_indexes) = 0; - virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type); + virtual bool IsTemplateType(lldb::opaque_compiler_type_t type); + + virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, + bool expand_pack); virtual lldb::TemplateArgumentKind - GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx); - virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, - size_t idx); - virtual llvm::Optional - GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx); + GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack); + virtual CompilerType + GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack); + virtual std::optional + GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, + bool expand_pack); // Dumping types @@ -363,7 +380,7 @@ public: LLVM_DUMP_METHOD virtual void dump(lldb::opaque_compiler_type_t type) const = 0; #endif - + virtual void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const DataExtractor &data, @@ -392,6 +409,12 @@ public: lldb::opaque_compiler_type_t type, Stream *s, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; + /// Dump a textual representation of the internal TypeSystem state to the + /// given stream. + /// + /// This should not modify the state of the TypeSystem if possible. + virtual void Dump(llvm::raw_ostream &output) = 0; + // TODO: These methods appear unused. Should they be removed? virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0; @@ -412,7 +435,7 @@ public: virtual bool IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) = 0; - virtual llvm::Optional + virtual std::optional GetTypeBitAlign(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) = 0; @@ -494,8 +517,15 @@ public: // meaningless type itself, instead preferring to use the dynamic type virtual bool IsMeaninglessWithoutDynamicResolution(void *type); + virtual std::optional ReportStatistics(); + + bool GetHasForcefullyCompletedTypes() const { + return m_has_forcefully_completed_types; + } protected: SymbolFile *m_sym_file = nullptr; + /// Used for reporting statistics. + bool m_has_forcefully_completed_types = false; }; class TypeSystemMap { @@ -509,39 +539,44 @@ public: // 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); + void ForEach(std::function const &callback); - llvm::Expected + llvm::Expected GetTypeSystemForLanguage(lldb::LanguageType language, Module *module, bool can_create); - llvm::Expected + llvm::Expected GetTypeSystemForLanguage(lldb::LanguageType language, Target *target, bool can_create); + /// Check all type systems in the map to see if any have forcefully completed + /// types; + bool GetHasForcefullyCompletedTypes() const; protected: - typedef std::map collection; + typedef llvm::DenseMap collection; mutable std::mutex m_mutex; ///< A mutex to keep this object happy in - ///multi-threaded environments. + /// multi-threaded environments. collection m_map; bool m_clear_in_progress = false; private: typedef llvm::function_ref CreateCallback; /// Finds the type system for the given language. If no type system could be - /// found for a language and a CreateCallback was provided, the value returned - /// by the callback will be treated as the TypeSystem for the language. + /// found for a language and a CreateCallback was provided, the value + /// returned by the callback will be treated as the TypeSystem for the + /// language. /// /// \param language The language for which the type system should be found. /// \param create_callback A callback that will be called if no previously /// created TypeSystem that fits the given language /// could found. Can be omitted if a non-existent - /// type system should be treated as an error instead. + /// type system should be treated as an error + /// instead. /// \return The found type system or an error. - llvm::Expected GetTypeSystemForLanguage( + llvm::Expected GetTypeSystemForLanguage( lldb::LanguageType language, - llvm::Optional create_callback = llvm::None); -}; + std::optional create_callback = std::nullopt); + }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Symbol/UnwindPlan.h b/gnu/llvm/lldb/include/lldb/Symbol/UnwindPlan.h index cc2302d2583..ebb0ec421da 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/UnwindPlan.h @@ -395,12 +395,10 @@ public: typedef std::shared_ptr RowSP; UnwindPlan(lldb::RegisterKind reg_kind) - : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind), - m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(), + : m_register_kind(reg_kind), m_return_addr_register(LLDB_INVALID_REGNUM), m_plan_is_sourced_from_compiler(eLazyBoolCalculate), m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate), - m_plan_is_for_signal_trap(eLazyBoolCalculate), - m_lsda_address(), m_personality_func_addr() {} + m_plan_is_for_signal_trap(eLazyBoolCalculate) {} // Performs a deep copy of the plan, including all the rows (expensive). UnwindPlan(const UnwindPlan &rhs) @@ -442,7 +440,7 @@ public: m_return_addr_register = regnum; } - uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; } + uint32_t GetReturnAddressRegister() { return m_return_addr_register; } uint32_t GetInitialCFARegister() const { if (m_row_list.empty()) diff --git a/gnu/llvm/lldb/include/lldb/Symbol/UnwindTable.h b/gnu/llvm/lldb/include/lldb/Symbol/UnwindTable.h index 9548b1f3fce..a3026504dbd 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/UnwindTable.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/UnwindTable.h @@ -11,6 +11,7 @@ #include #include +#include #include "lldb/lldb-private.h" @@ -60,8 +61,8 @@ private: void Dump(Stream &s); void Initialize(); - llvm::Optional GetAddressRange(const Address &addr, - SymbolContext &sc); + std::optional GetAddressRange(const Address &addr, + SymbolContext &sc); typedef std::map collection; typedef collection::iterator iterator; diff --git a/gnu/llvm/lldb/include/lldb/Symbol/Variable.h b/gnu/llvm/lldb/include/lldb/Symbol/Variable.h index ccd5072c3d2..c437624d1ea 100644 --- a/gnu/llvm/lldb/include/lldb/Symbol/Variable.h +++ b/gnu/llvm/lldb/include/lldb/Symbol/Variable.h @@ -11,7 +11,7 @@ #include "lldb/Core/Declaration.h" #include "lldb/Core/Mangled.h" -#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Expression/DWARFExpressionList.h" #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/UserID.h" @@ -32,8 +32,8 @@ public: Variable(lldb::user_id_t uid, const char *name, const char *mangled, const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope, SymbolContextScope *owner_scope, const RangeList &scope_range, - Declaration *decl, const DWARFExpression &location, bool external, - bool artificial, bool location_is_constant_data, + Declaration *decl, const DWARFExpressionList &location, + bool external, bool artificial, bool location_is_constant_data, bool static_member = false); virtual ~Variable(); @@ -73,11 +73,15 @@ public: bool IsStaticMember() const { return m_static_member; } - DWARFExpression &LocationExpression() { return m_location; } + DWARFExpressionList &LocationExpressionList() { return m_location_list; } - const DWARFExpression &LocationExpression() const { return m_location; } + const DWARFExpressionList &LocationExpressionList() const { + return m_location_list; + } - bool DumpLocationForAddress(Stream *s, const Address &address); + // When given invalid address, it dumps all locations. Otherwise it only dumps + // the location that contains this address. + bool DumpLocations(Stream *s, const Address &address); size_t MemorySize() const; @@ -126,7 +130,7 @@ protected: Declaration m_declaration; /// The location of this variable that can be fed to /// DWARFExpression::Evaluate(). - DWARFExpression m_location; + DWARFExpressionList m_location_list; /// Visible outside the containing compile unit? unsigned m_external : 1; /// Non-zero if the variable is not explicitly declared in source. diff --git a/gnu/llvm/lldb/include/lldb/Target/ABI.h b/gnu/llvm/lldb/include/lldb/Target/ABI.h index 8fbb6aae68c..f0753172d3e 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ABI.h +++ b/gnu/llvm/lldb/include/lldb/Target/ABI.h @@ -11,6 +11,7 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/DynamicRegisterInfo.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-private.h" @@ -125,9 +126,24 @@ public: virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) { return pc; } /// @} + /// Use this method when you do not know, or do not care what kind of address + /// you are fixing. On platforms where there would be a difference between the + /// two types, it will pick the safest option. + /// + /// Its purpose is to signal that no specific choice was made and provide an + /// alternative to randomly picking FixCode/FixData address. Which could break + /// platforms where there is a difference (only Arm Thumb at this time). + virtual lldb::addr_t FixAnyAddress(lldb::addr_t pc) { + // On Arm Thumb fixing a code address zeroes the bottom bit, so FixData is + // the safe choice. On any other platform (so far) code and data addresses + // are fixed in the same way. + return FixDataAddress(pc); + } + llvm::MCRegisterInfo &GetMCRegisterInfo() { return *m_mc_register_info_up; } - virtual void AugmentRegisterInfo(RegisterInfo &info) = 0; + virtual void + AugmentRegisterInfo(std::vector ®s) = 0; virtual bool GetPointerReturnRegister(const char *&name) { return false; } @@ -159,7 +175,8 @@ private: class RegInfoBasedABI : public ABI { public: - void AugmentRegisterInfo(RegisterInfo &info) override; + void AugmentRegisterInfo( + std::vector ®s) override; protected: using ABI::ABI; @@ -171,12 +188,14 @@ protected: class MCBasedABI : public ABI { public: - void AugmentRegisterInfo(RegisterInfo &info) override; + void AugmentRegisterInfo( + std::vector ®s) override; /// If the register name is of the form "[]" then change /// the name to "[]". Otherwise, leave the name unchanged. static void MapRegisterName(std::string ®, llvm::StringRef from_prefix, - llvm::StringRef to_prefix); + llvm::StringRef to_prefix); + protected: using ABI::ABI; diff --git a/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.def b/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.def new file mode 100644 index 00000000000..9a938c3b302 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.def @@ -0,0 +1,50 @@ +/*===-- AppleArm64ExceptionClass.def ---------------------------*- C++ -*-=== *\ +|* +|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +|* See https://llvm.org/LICENSE.txt for license information. +|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +|* +\*===----------------------------------------------------------------------===*/ + +// Defines ESR exception classes for Apple arm64* targets. +// These largely map 1:1 to the exception classes defined in ARM's architecture +// reference manual, but there are some Apple-specific additions. + +#ifndef APPLE_ARM64_EXCEPTION_CLASS +#error "APPLE_ARM64_EXCEPTION_CLASS(Name, Code) not defined." +#endif + +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_UNCATEGORIZED, 0x00) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_WFI_WFE, 0x01) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_MCR_MRC_CP15_TRAP, 0x03) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_MCRR_MRRC_CP15_TRAP, 0x04) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_MCR_MRC_CP14_TRAP, 0x05) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_LDC_STC_CP14_TRAP, 0x06) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_TRAP_SIMD_FP, 0x07) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_PTRAUTH_INSTR_TRAP, 0x09) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_MCRR_MRRC_CP14_TRAP, 0x0c) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_ILLEGAL_INSTR_SET, 0x0e) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SVC_32, 0x11) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SVC_64, 0x15) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_MSR_TRAP, 0x18) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_PAC_FAIL, 0x1C) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_IABORT_EL0, 0x20) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_IABORT_EL1, 0x21) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_PC_ALIGN, 0x22) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_DABORT_EL0, 0x24) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_DABORT_EL1, 0x25) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SP_ALIGN, 0x26) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_FLOATING_POINT_32, 0x28) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_FLOATING_POINT_64, 0x2C) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SERROR_INTERRUPT, 0x2F) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_BKPT_REG_MATCH_EL0, 0x30) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_BKPT_REG_MATCH_EL1, 0x31) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SW_STEP_DEBUG_EL0, 0x32) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_SW_STEP_DEBUG_EL1, 0x33) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_WATCHPT_MATCH_EL0, 0x34) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_WATCHPT_MATCH_EL1, 0x35) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_BKPT_AARCH32, 0x38) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_BRK_AARCH64, 0x3C) +APPLE_ARM64_EXCEPTION_CLASS(ESR_EC_PRIV, 0x3F) + +#undef APPLE_ARM64_EXCEPTION_CLASS diff --git a/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.h b/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.h new file mode 100644 index 00000000000..95f58ee081a --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/AppleArm64ExceptionClass.h @@ -0,0 +1,50 @@ +//===-- AppleArm64ExceptionClass.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_APPLEARM64EXCEPTIONCLASS_H +#define LLDB_TARGET_APPLEARM64EXCEPTIONCLASS_H + +#include + +namespace lldb_private { + +enum class AppleArm64ExceptionClass : unsigned { +#define APPLE_ARM64_EXCEPTION_CLASS(Name, Code) Name = Code, +#include "AppleArm64ExceptionClass.def" +}; + +/// Get the Apple ARM64 exception class encoded within \p esr. +inline AppleArm64ExceptionClass getAppleArm64ExceptionClass(uint32_t esr) { + /* + * Exception Syndrome Register + * + * 31 26 25 24 0 + * +------+--+------------------+ + * | EC |IL| ISS | + * +------+--+------------------+ + * + * EC - Exception Class + * IL - Instruction Length + * ISS - Instruction Specific Syndrome + */ + return static_cast(esr >> 26); +} + +inline const char *toString(AppleArm64ExceptionClass EC) { + switch (EC) { +#define APPLE_ARM64_EXCEPTION_CLASS(Name, Code) \ + case AppleArm64ExceptionClass::Name: \ + return #Name; +#include "AppleArm64ExceptionClass.def" + } + return "Unknown Exception Class"; +} + +} // namespace lldb_private + +#endif // LLDB_TARGET_APPLEARM64EXCEPTIONCLASS_H diff --git a/gnu/llvm/lldb/include/lldb/Target/DynamicLoader.h b/gnu/llvm/lldb/include/lldb/Target/DynamicLoader.h index a904fac0c77..22d047ab4b6 100644 --- a/gnu/llvm/lldb/include/lldb/Target/DynamicLoader.h +++ b/gnu/llvm/lldb/include/lldb/Target/DynamicLoader.h @@ -62,8 +62,9 @@ public: /// /// \param[in] plugin_name /// An optional name of a specific dynamic loader plug-in that - /// should be used. If NULL, pick the best plug-in. - static DynamicLoader *FindPlugin(Process *process, const char *plugin_name); + /// should be used. If empty, pick the best plug-in. + static DynamicLoader *FindPlugin(Process *process, + llvm::StringRef plugin_name); /// Construct with a process. DynamicLoader(Process *process); @@ -202,11 +203,65 @@ public: /// Locates or creates a module given by \p file and updates/loads the /// resulting module at the virtual base address \p base_addr. + /// Note that this calls Target::GetOrCreateModule with notify being false, + /// so it is necessary to call Target::ModulesDidLoad afterwards. 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); + /// Find/load a binary into lldb given a UUID and the address where it is + /// loaded in memory, or a slide to be applied to the file address. + /// May force an expensive search on the computer to find the binary by + /// UUID, should not be used for a large number of binaries - intended for + /// an environment where there may be one, or a few, binaries resident in + /// memory. + /// + /// Given a UUID, search for a binary and load it at the address provided, + /// or with the slide applied, or at the file address unslid. + /// + /// Given an address, try to read the binary out of memory, get the UUID, + /// find the file if possible and load it unslid, or add the memory module. + /// + /// \param[in] process + /// The process to add this binary to. + /// + /// \param[in] name + /// Name of the binary, if available. If this method cannot find a + /// matching binary on the debug host, it may create a memory module + /// out of live memory, and the provided name will be used. If an + /// empty StringRef is provided, a name will be constructed for the module + /// based on the address it is loaded at. + /// + /// \param[in] uuid + /// UUID of the binary to be loaded. UUID may be empty, and if a + /// load address is supplied, will read the binary from memory, get + /// a UUID and try to find a local binary. There is a performance + /// cost to doing this, it is not preferable. + /// + /// \param[in] value + /// Address where the binary should be loaded, or read out of memory. + /// Or a slide value, to be applied to the file addresses of the binary. + /// + /// \param[in] value_is_offset + /// A flag indicating that \p value is an address, or an offset to + /// be applied to the file addresses. + /// + /// \param[in] force_symbol_search + /// Allow the search to do a possibly expensive external search for + /// the ObjectFile and/or SymbolFile. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called when a binary has been added + /// to the Target. The caller may prefer to batch up these when loading + /// multiple binaries. + /// + /// \return + /// Returns a shared pointer for the Module that has been added. + static lldb::ModuleSP LoadBinaryWithUUIDAndAddress( + Process *process, llvm::StringRef name, UUID uuid, lldb::addr_t value, + bool value_is_offset, bool force_symbol_search, bool notify); + /// Get information about the shared cache for a process, if possible. /// /// On some systems (e.g. Darwin based systems), a set of libraries that are @@ -262,6 +317,8 @@ public: protected: // Utility methods for derived classes + lldb::ModuleSP FindModuleViaTarget(const FileSpec &file); + /// Checks to see if the target module has changed, updates the target /// accordingly and returns the target executable module. lldb::ModuleSP GetTargetExecutable(); diff --git a/gnu/llvm/lldb/include/lldb/Target/DynamicRegisterInfo.h b/gnu/llvm/lldb/include/lldb/Target/DynamicRegisterInfo.h new file mode 100644 index 00000000000..20f442529da --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/DynamicRegisterInfo.h @@ -0,0 +1,136 @@ +//===-- DynamicRegisterInfo.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_DYNAMICREGISTERINFO_H +#define LLDB_TARGET_DYNAMICREGISTERINFO_H + +#include +#include + +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class DynamicRegisterInfo { +protected: + DynamicRegisterInfo(DynamicRegisterInfo &) = default; + DynamicRegisterInfo &operator=(DynamicRegisterInfo &) = default; + +public: + struct Register { + ConstString name; + ConstString alt_name; + ConstString set_name; + uint32_t byte_size = LLDB_INVALID_INDEX32; + uint32_t byte_offset = LLDB_INVALID_INDEX32; + lldb::Encoding encoding = lldb::eEncodingUint; + lldb::Format format = lldb::eFormatHex; + uint32_t regnum_dwarf = LLDB_INVALID_REGNUM; + uint32_t regnum_ehframe = LLDB_INVALID_REGNUM; + uint32_t regnum_generic = LLDB_INVALID_REGNUM; + uint32_t regnum_remote = LLDB_INVALID_REGNUM; + std::vector value_regs; + std::vector invalidate_regs; + uint32_t value_reg_offset = 0; + }; + + DynamicRegisterInfo() = default; + + DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, + const lldb_private::ArchSpec &arch); + + virtual ~DynamicRegisterInfo() = default; + + DynamicRegisterInfo(DynamicRegisterInfo &&info); + DynamicRegisterInfo &operator=(DynamicRegisterInfo &&info); + + size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict, + const lldb_private::ArchSpec &arch); + + size_t SetRegisterInfo(std::vector &®s, + const lldb_private::ArchSpec &arch); + + size_t GetNumRegisters() const; + + size_t GetNumRegisterSets() const; + + size_t GetRegisterDataByteSize() const; + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(uint32_t i) const; + + const lldb_private::RegisterSet *GetRegisterSet(uint32_t i) const; + + uint32_t GetRegisterSetIndexByName(const lldb_private::ConstString &set_name, + bool can_create); + + uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) const; + + const lldb_private::RegisterInfo *GetRegisterInfo(uint32_t kind, + uint32_t num) const; + + void Dump() const; + + void Clear(); + + bool IsReconfigurable(); + + const lldb_private::RegisterInfo * + GetRegisterInfo(llvm::StringRef reg_name) const; + + typedef std::vector reg_collection; + llvm::iterator_range registers() const { + return llvm::iterator_range(m_regs); + } + +protected: + // Classes that inherit from DynamicRegisterInfo can see and modify these + typedef std::vector set_collection; + typedef std::vector reg_num_collection; + typedef std::vector set_reg_num_collection; + typedef std::vector name_collection; + typedef std::map reg_to_regs_map; + typedef std::map reg_offset_map; + + llvm::Expected ByteOffsetFromSlice(uint32_t index, + llvm::StringRef slice_str, + lldb::ByteOrder byte_order); + llvm::Expected ByteOffsetFromComposite( + uint32_t index, lldb_private::StructuredData::Array &composite_reg_list, + lldb::ByteOrder byte_order); + llvm::Expected ByteOffsetFromRegInfoDict( + uint32_t index, lldb_private::StructuredData::Dictionary ®_info_dict, + lldb::ByteOrder byte_order); + + void MoveFrom(DynamicRegisterInfo &&info); + + void Finalize(const lldb_private::ArchSpec &arch); + + void ConfigureOffsets(); + + reg_collection m_regs; + set_collection m_sets; + set_reg_num_collection m_set_reg_nums; + name_collection m_set_names; + reg_to_regs_map m_value_regs_map; + reg_to_regs_map m_invalidate_regs_map; + reg_offset_map m_value_reg_offset_map; + size_t m_reg_data_byte_size = 0u; // The number of bytes required to store + // all registers + bool m_finalized = false; + bool m_is_reconfigurable = false; +}; + +void addSupplementaryRegister(std::vector ®s, + DynamicRegisterInfo::Register new_reg_info); + +} // namespace lldb_private + +#endif // LLDB_TARGET_DYNAMICREGISTERINFO_H diff --git a/gnu/llvm/lldb/include/lldb/Target/InstrumentationRuntime.h b/gnu/llvm/lldb/include/lldb/Target/InstrumentationRuntime.h index eeec91f36af..a6121c24b95 100644 --- a/gnu/llvm/lldb/include/lldb/Target/InstrumentationRuntime.h +++ b/gnu/llvm/lldb/include/lldb/Target/InstrumentationRuntime.h @@ -42,8 +42,7 @@ class InstrumentationRuntime protected: InstrumentationRuntime(const lldb::ProcessSP &process_sp) - : m_process_wp(), m_runtime_module(), m_breakpoint_id(0), - m_is_active(false) { + : m_breakpoint_id(0), m_is_active(false) { if (process_sp) m_process_wp = process_sp; } diff --git a/gnu/llvm/lldb/include/lldb/Target/Language.h b/gnu/llvm/lldb/include/lldb/Target/Language.h index 11b9daa3894..8cc1e72e138 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Language.h +++ b/gnu/llvm/lldb/include/lldb/Target/Language.h @@ -57,8 +57,7 @@ public: class ImageListTypeScavenger : public TypeScavenger { class Result : public Language::TypeScavenger::Result { public: - Result(CompilerType type) - : Language::TypeScavenger::Result(), m_compiler_type(type) {} + Result(CompilerType type) : m_compiler_type(type) {} bool IsValid() override { return m_compiler_type.IsValid(); } @@ -95,7 +94,7 @@ public: template class EitherTypeScavenger : public TypeScavenger { public: - EitherTypeScavenger() : TypeScavenger(), m_scavengers() { + EitherTypeScavenger() : TypeScavenger() { for (std::shared_ptr scavenger : { std::shared_ptr(new ScavengerTypes())... }) { if (scavenger) m_scavengers.push_back(scavenger); @@ -118,7 +117,7 @@ public: template class UnionTypeScavenger : public TypeScavenger { public: - UnionTypeScavenger() : TypeScavenger(), m_scavengers() { + UnionTypeScavenger() : TypeScavenger() { for (std::shared_ptr scavenger : { std::shared_ptr(new ScavengerTypes())... }) { if (scavenger) m_scavengers.push_back(scavenger); @@ -176,7 +175,7 @@ public: virtual HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics(); - virtual std::vector + virtual std::vector GetPossibleFormattersMatches(ValueObject &valobj, lldb::DynamicValueType use_dynamic); @@ -218,6 +217,17 @@ public: std::string &prefix, std::string &suffix); + // When looking up functions, we take a user provided string which may be a + // partial match to the full demangled name and compare it to the actual + // demangled name to see if it matches as much as the user specified. An + // example of this is if the user provided A::my_function, but the + // symbol was really B::A::my_function. We want that to be + // a match. But we wouldn't want this to match AnotherA::my_function. The + // user is specifying a truncated path, not a truncated set of characters. + // This function does a language-aware comparison for those purposes. + virtual bool DemangledNameContainsPath(llvm::StringRef path, + ConstString demangled) const; + // 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(); @@ -243,6 +253,14 @@ public: FunctionNameRepresentation representation, Stream &s); + virtual ConstString + GetDemangledFunctionNameWithoutArguments(Mangled mangled) const { + if (ConstString demangled = mangled.GetDemangledName()) + return demangled; + + return mangled.GetMangledName(); + } + virtual void GetExceptionResolverDescription(bool catch_on, bool throw_on, Stream &s); @@ -261,6 +279,16 @@ public: static void PrintAllLanguages(Stream &s, const char *prefix, const char *suffix); + /// Prints to the specified stream 's' each language type that the + /// current target supports for expression evaluation. + /// + /// \param[out] s Stream to which the language types are written. + /// \param[in] prefix String that is prepended to the language type. + /// \param[in] suffix String that is appended to the language type. + static void PrintSupportedLanguagesForExpressions(Stream &s, + llvm::StringRef prefix, + llvm::StringRef suffix); + // return false from callback to stop iterating static void ForAllLanguages(std::function callback); @@ -285,6 +313,19 @@ public: static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions(); static LanguageSet GetLanguagesSupportingREPLs(); + // Given a mangled function name, calculates some alternative manglings since + // the compiler mangling may not line up with the symbol we are expecting. + virtual std::vector + GenerateAlternateFunctionManglings(const ConstString mangled) const { + return std::vector(); + } + + virtual ConstString + FindBestAlternateFunctionMangledName(const Mangled mangled, + const SymbolContext &sym_ctx) const { + return ConstString(); + } + protected: // Classes that inherit from Language can see and modify these diff --git a/gnu/llvm/lldb/include/lldb/Target/LanguageRuntime.h b/gnu/llvm/lldb/include/lldb/Target/LanguageRuntime.h index 2f95c264331..9cc79dc976c 100644 --- a/gnu/llvm/lldb/include/lldb/Target/LanguageRuntime.h +++ b/gnu/llvm/lldb/include/lldb/Target/LanguageRuntime.h @@ -21,6 +21,7 @@ #include "lldb/Target/Runtime.h" #include "lldb/lldb-private.h" #include "lldb/lldb-public.h" +#include namespace lldb_private { @@ -141,7 +142,7 @@ public: return false; } - virtual void SymbolsDidLoad(const ModuleList &module_list) { return; } + virtual void SymbolsDidLoad(const ModuleList &module_list) {} virtual lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop_others) = 0; @@ -150,11 +151,11 @@ public: /// from the user interface. virtual bool IsAllowedRuntimeValue(ConstString name) { return false; } - virtual llvm::Optional GetRuntimeType(CompilerType base_type) { - return llvm::None; + virtual std::optional GetRuntimeType(CompilerType base_type) { + return std::nullopt; } - virtual void ModulesDidLoad(const ModuleList &module_list) override {} + void ModulesDidLoad(const ModuleList &module_list) override {} // Called by ClangExpressionParser::PrepareForExecution to query for any // custom LLVM IR passes that need to be run before an expression is diff --git a/gnu/llvm/lldb/include/lldb/Target/Memory.h b/gnu/llvm/lldb/include/lldb/Target/Memory.h index b3ad22aff16..8c564e8f5a8 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Memory.h +++ b/gnu/llvm/lldb/include/lldb/Target/Memory.h @@ -116,7 +116,7 @@ public: ~AllocatedMemoryCache(); - void Clear(); + void Clear(bool deallocate_memory); lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, Status &error); diff --git a/gnu/llvm/lldb/include/lldb/Target/MemoryRegionInfo.h b/gnu/llvm/lldb/include/lldb/Target/MemoryRegionInfo.h index c43f27e0c36..47d4c9d6398 100644 --- a/gnu/llvm/lldb/include/lldb/Target/MemoryRegionInfo.h +++ b/gnu/llvm/lldb/include/lldb/Target/MemoryRegionInfo.h @@ -10,11 +10,11 @@ #ifndef LLDB_TARGET_MEMORYREGIONINFO_H #define LLDB_TARGET_MEMORYREGIONINFO_H +#include #include #include "lldb/Utility/ConstString.h" #include "lldb/Utility/RangeMap.h" -#include "llvm/ADT/Optional.h" #include "llvm/Support/FormatProviders.h" namespace lldb_private { @@ -26,12 +26,14 @@ public: MemoryRegionInfo() = default; MemoryRegionInfo(RangeType range, OptionalBool read, OptionalBool write, - OptionalBool execute, OptionalBool mapped, ConstString name, + OptionalBool execute, OptionalBool shared, + OptionalBool mapped, ConstString name, OptionalBool flash, lldb::offset_t blocksize, - OptionalBool memory_tagged) + OptionalBool memory_tagged, OptionalBool stack_memory) : m_range(range), m_read(read), m_write(write), m_execute(execute), - m_mapped(mapped), m_name(name), m_flash(flash), m_blocksize(blocksize), - m_memory_tagged(memory_tagged) {} + m_shared(shared), m_mapped(mapped), m_name(name), m_flash(flash), + m_blocksize(blocksize), m_memory_tagged(memory_tagged), + m_is_stack_memory(stack_memory) {} RangeType &GetRange() { return m_range; } @@ -45,6 +47,8 @@ public: OptionalBool GetExecutable() const { return m_execute; } + OptionalBool GetShared() const { return m_shared; } + OptionalBool GetMapped() const { return m_mapped; } ConstString GetName() const { return m_name; } @@ -57,6 +61,8 @@ public: void SetExecutable(OptionalBool val) { m_execute = val; } + void SetShared(OptionalBool val) { m_shared = val; } + void SetMapped(OptionalBool val) { m_mapped = val; } void SetName(const char *name) { m_name = ConstString(name); } @@ -95,10 +101,12 @@ public: bool operator==(const MemoryRegionInfo &rhs) const { return m_range == rhs.m_range && m_read == rhs.m_read && m_write == rhs.m_write && m_execute == rhs.m_execute && + m_shared == rhs.m_shared && m_mapped == rhs.m_mapped && m_name == rhs.m_name && m_flash == rhs.m_flash && m_blocksize == rhs.m_blocksize && m_memory_tagged == rhs.m_memory_tagged && - m_pagesize == rhs.m_pagesize; + m_pagesize == rhs.m_pagesize && + m_is_stack_memory == rhs.m_is_stack_memory; } bool operator!=(const MemoryRegionInfo &rhs) const { return !(*this == rhs); } @@ -106,21 +114,25 @@ public: /// Get the target system's VM page size in bytes. /// \return /// 0 is returned if this information is unavailable. - int GetPageSize() { return m_pagesize; } + int GetPageSize() const { return m_pagesize; } /// Get a vector of target VM pages that are dirty -- that have been /// modified -- within this memory region. This is an Optional return /// value; it will only be available if the remote stub was able to /// detail this. - llvm::Optional> &GetDirtyPageList() { + const std::optional> &GetDirtyPageList() const { return m_dirty_pages; } + OptionalBool IsStackMemory() const { return m_is_stack_memory; } + + void SetIsStackMemory(OptionalBool val) { m_is_stack_memory = val; } + void SetPageSize(int pagesize) { m_pagesize = pagesize; } void SetDirtyPageList(std::vector pagelist) { - if (m_dirty_pages.hasValue()) - m_dirty_pages.getValue().clear(); + if (m_dirty_pages) + m_dirty_pages->clear(); m_dirty_pages = std::move(pagelist); } @@ -129,13 +141,15 @@ protected: OptionalBool m_read = eDontKnow; OptionalBool m_write = eDontKnow; OptionalBool m_execute = eDontKnow; + OptionalBool m_shared = eDontKnow; OptionalBool m_mapped = eDontKnow; ConstString m_name; OptionalBool m_flash = eDontKnow; lldb::offset_t m_blocksize = 0; OptionalBool m_memory_tagged = eDontKnow; + OptionalBool m_is_stack_memory = eDontKnow; int m_pagesize = 0; - llvm::Optional> m_dirty_pages; + std::optional> m_dirty_pages; }; inline bool operator<(const MemoryRegionInfo &lhs, diff --git a/gnu/llvm/lldb/include/lldb/Target/MemoryTagManager.h b/gnu/llvm/lldb/include/lldb/Target/MemoryTagManager.h index a5e0deba14a..b082224c38e 100644 --- a/gnu/llvm/lldb/include/lldb/Target/MemoryTagManager.h +++ b/gnu/llvm/lldb/include/lldb/Target/MemoryTagManager.h @@ -35,8 +35,8 @@ public: // you get will have been shifted down 56 before being returned. virtual lldb::addr_t GetLogicalTag(lldb::addr_t addr) const = 0; - // Remove non address bits from a pointer - virtual lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const = 0; + // Remove tag bits from a pointer + virtual lldb::addr_t RemoveTagBits(lldb::addr_t addr) const = 0; // Return the difference between two addresses, ignoring any logical tags they // have. If your tags are just part of a larger set of ignored bits, this @@ -64,7 +64,7 @@ public: // (which may include one or more memory regions) // // If so, return a modified range which will have been expanded - // to be granule aligned. + // to be granule aligned. Otherwise return an error. // // Tags in the input addresses are ignored and not present // in the returned range. @@ -72,6 +72,23 @@ public: lldb::addr_t addr, lldb::addr_t end_addr, const lldb_private::MemoryRegionInfos &memory_regions) const = 0; + // Given a range addr to end_addr, check that end_addr >= addr. + // If it is not, return an error saying so. + // Otherwise, granule align it and return a set of ranges representing + // subsections of the aligned range that have memory tagging enabled. + // + // Basically a sparse version of MakeTaggedRange. Use this when you + // want to know which parts of a larger range have memory tagging. + // + // Regions in memory_regions should be sorted in ascending order and + // not overlap. (use Process GetMemoryRegions) + // + // Tags in the input addresses are ignored and not present + // in the returned ranges. + virtual llvm::Expected> MakeTaggedRanges( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const = 0; + // Return the type value to use in GDB protocol qMemTags packets to read // allocation tags. This is named "Allocation" specifically because the spec // allows for logical tags to be read the same way, though we do not use that. @@ -96,6 +113,21 @@ public: UnpackTagsData(const std::vector &tags, size_t granules = 0) const = 0; + // Unpack tags from a corefile segment containing compressed tags + // (compression that may be different from the one used for GDB transport). + // + // This method asumes that: + // * addr and len have been granule aligned by a tag manager + // * addr >= tag_segment_virtual_address + // + // 'reader' will always be a wrapper around a CoreFile in real use + // but allows testing without having to mock a CoreFile. + typedef std::function CoreReaderFn; + std::vector virtual UnpackTagsFromCoreFileSegment( + CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address, + lldb::addr_t tag_segment_data_address, lldb::addr_t addr, + size_t len) const = 0; + // Pack uncompressed tags into their storage format (e.g. for gdb QMemTags). // Checks that each tag is within the expected value range. // We do not check the number of tags or range they apply to because @@ -127,7 +159,7 @@ public: RepeatTagsForRange(const std::vector &tags, TagRange range) const = 0; - virtual ~MemoryTagManager() {} + virtual ~MemoryTagManager() = default; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Target/MemoryTagMap.h b/gnu/llvm/lldb/include/lldb/Target/MemoryTagMap.h new file mode 100644 index 00000000000..272f722dbfb --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/MemoryTagMap.h @@ -0,0 +1,98 @@ +//===-- MemoryTagMap.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_MEMORYTAGMAP_H +#define LLDB_TARGET_MEMORYTAGMAP_H + +#include "lldb/Target/MemoryTagManager.h" +#include "lldb/lldb-private.h" +#include +#include + +namespace lldb_private { + +/// MemoryTagMap provides a way to give a sparse read result +/// when reading memory tags for a range. This is useful when +/// you want to annotate some large memory dump that might include +/// tagged memory but you don't know that it is all tagged. +class MemoryTagMap { +public: + /// Init an empty tag map + /// + /// \param [in] manager + /// Non-null pointer to a memory tag manager. + MemoryTagMap(const MemoryTagManager *manager); + + /// Insert tags into the map starting from addr. + /// + /// \param [in] addr + /// Start address of the range to insert tags for. + /// This address should be granule aligned and have had + /// any non address bits removed. + /// (ideally you would use the base of the range you used + /// to read the tags in the first place) + /// + /// \param [in] tags + /// Vector of tags to insert. The first tag will be inserted + /// at addr, the next at addr+granule size and so on until + /// all tags have been inserted. + void InsertTags(lldb::addr_t addr, const std::vector tags); + + bool Empty() const; + + /// Lookup memory tags for a range of memory from addr to addr+len. + /// + /// \param [in] addr + /// The start of the range. This may include non address bits and + /// does not have to be granule aligned. + /// + /// \param [in] len + /// The length in bytes of the range to read tags for. This does + /// not need to be multiple of the granule size. + /// + /// \return + /// A vector containing the tags found for the granules in the + /// range. (which is the result of granule aligning the given range) + /// + /// Each item in the vector is an optional tag. Meaning that if + /// it is valid then the granule had a tag and if not, it didn't. + /// + /// If the range had no tags at all, the vector will be empty. + /// If some of the range was tagged it will have items and some + /// of them may be std::nullopt. + /// (this saves the caller checking whether all items are std::nullopt) + std::vector> GetTags(lldb::addr_t addr, + size_t len) const; + +private: + /// Lookup the tag for address + /// + /// \param [in] address + /// The address to lookup a tag for. This should be aligned + /// to a granule boundary. + /// + /// \return + /// The tag for the granule that address refers to, or std::nullopt + /// if it has no memory tag. + std::optional GetTag(lldb::addr_t addr) const; + + // A map of granule aligned addresses to their memory tag + std::map m_addr_to_tag; + + // Memory tag manager used to align addresses and get granule size. + // Ideally this would be a const& but only certain architectures will + // have a memory tag manager class to provide here. So for a method + // returning a MemoryTagMap, std::optional allows it to handle + // architectures without memory tagging. Optionals cannot hold references + // so we go with a pointer that we assume will be not be null. + const MemoryTagManager *m_manager; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_MEMORYTAGMAP_H diff --git a/gnu/llvm/lldb/include/lldb/Target/PathMappingList.h b/gnu/llvm/lldb/include/lldb/Target/PathMappingList.h index d788d120c47..447fb43f4d6 100644 --- a/gnu/llvm/lldb/include/lldb/Target/PathMappingList.h +++ b/gnu/llvm/lldb/include/lldb/Target/PathMappingList.h @@ -9,10 +9,12 @@ #ifndef LLDB_TARGET_PATHMAPPINGLIST_H #define LLDB_TARGET_PATHMAPPINGLIST_H -#include -#include #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" +#include "llvm/Support/JSON.h" +#include +#include +#include namespace lldb_private { @@ -32,16 +34,22 @@ public: const PathMappingList &operator=(const PathMappingList &rhs); - void Append(ConstString path, ConstString replacement, - bool notify); + void Append(llvm::StringRef path, llvm::StringRef replacement, bool notify); void Append(const PathMappingList &rhs, bool notify); + /// Append pair without duplication. + /// \return whether appending suceeds without duplication or not. + bool AppendUnique(llvm::StringRef path, llvm::StringRef replacement, + bool notify); + void Clear(bool notify); // By default, dump all pairs. void Dump(Stream *s, int pair_index = -1); + llvm::json::Value ToJSON(); + bool IsEmpty() const { return m_pairs.empty(); } size_t GetSize() const { return m_pairs.size(); } @@ -49,17 +57,16 @@ public: bool GetPathsAtIndex(uint32_t idx, ConstString &path, ConstString &new_path) const; - void Insert(ConstString path, ConstString replacement, + void Insert(llvm::StringRef path, llvm::StringRef replacement, uint32_t insert_idx, bool notify); bool Remove(size_t index, bool notify); bool Remove(ConstString path, bool notify); - bool Replace(ConstString path, ConstString replacement, - bool notify); + bool Replace(llvm::StringRef path, llvm::StringRef replacement, bool notify); - bool Replace(ConstString path, ConstString replacement, + bool Replace(llvm::StringRef path, llvm::StringRef replacement, uint32_t index, bool notify); bool RemapPath(ConstString path, ConstString &new_path) const; @@ -75,19 +82,34 @@ public: /// \param[in] only_if_exists /// If \b true, besides matching \p path with the remapping rules, this /// tries to check with the filesystem that the remapped file exists. If - /// no valid file is found, \b None is returned. This might be expensive, - /// specially on a network. + /// no valid file is found, \b std::nullopt is returned. This might be + /// expensive, specially on a network. /// /// If \b false, then the existence of the returned remapping is not /// checked. /// /// \return /// The remapped filespec that may or may not exist on disk. - llvm::Optional RemapPath(llvm::StringRef path, - bool only_if_exists = false) const; + std::optional RemapPath(llvm::StringRef path, + bool only_if_exists = false) const; bool RemapPath(const char *, std::string &) const = delete; - bool ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const; + /// Perform reverse source path remap for input \a file. + /// Source maps contains a list of mappings. + /// Reverse remap means locating a matching entry prefix using "to_new_path" + /// part and replacing it with "from_original_path" part if found. + /// + /// \param[in] file + /// The source path to reverse remap. + /// \param[in] fixed + /// The reversed mapped new path. + /// + /// \return + /// std::nullopt if no remapping happens, otherwise, the matching source + /// map entry's ""to_new_pathto"" part (which is the prefix of \a file) is + /// returned. + std::optional ReverseRemapPath(const FileSpec &file, + FileSpec &fixed) const; /// Finds a source file given a file spec using the path remappings. /// @@ -102,9 +124,9 @@ public: /// /// \return /// The newly remapped filespec that is guaranteed to exist. - llvm::Optional FindFile(const FileSpec &orig_spec) const; + std::optional FindFile(const FileSpec &orig_spec) const; - uint32_t FindIndexForPath(ConstString path) const; + uint32_t FindIndexForPath(llvm::StringRef path) const; uint32_t GetModificationID() const { return m_mod_id; } diff --git a/gnu/llvm/lldb/include/lldb/Target/Platform.h b/gnu/llvm/lldb/include/lldb/Target/Platform.h index df46466655c..08e47cc1324 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Platform.h +++ b/gnu/llvm/lldb/include/lldb/Target/Platform.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,6 @@ private: void SetDefaultModuleCacheDirectory(const FileSpec &dir_spec); }; -typedef std::shared_ptr PlatformPropertiesSP; typedef llvm::SmallVector MmapArgList; /// \class Platform Platform.h "lldb/Target/Platform.h" @@ -74,8 +74,6 @@ 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; @@ -84,7 +82,7 @@ public: static void Terminate(); - static const PlatformPropertiesSP &GetGlobalPlatformProperties(); + static PlatformProperties &GetGlobalPlatformProperties(); /// Get the native host platform plug-in. /// @@ -97,20 +95,11 @@ public: /// attaching to processes unless another platform is specified. static lldb::PlatformSP GetHostPlatform(); - static lldb::PlatformSP - GetPlatformForArchitecture(const ArchSpec &arch, ArchSpec *platform_arch_ptr); - static const char *GetHostPlatformName(); static void SetHostPlatform(const lldb::PlatformSP &platform_sp); - // Find an existing platform plug-in by name - static lldb::PlatformSP Find(ConstString name); - - static lldb::PlatformSP Create(ConstString name, Status &error); - - static lldb::PlatformSP Create(const ArchSpec &arch, - ArchSpec *platform_arch_ptr, Status &error); + static lldb::PlatformSP Create(llvm::StringRef name); /// Augments the triple either with information from platform or the host /// system (if platform is null). @@ -215,18 +204,18 @@ public: bool SetOSVersion(llvm::VersionTuple os_version); - bool GetOSBuildString(std::string &s); + std::optional GetOSBuildString(); - bool GetOSKernelDescription(std::string &s); + std::optional GetOSKernelDescription(); // Returns the name of the platform - ConstString GetName(); + llvm::StringRef GetName() { return GetPluginName(); } virtual const char *GetHostname(); virtual ConstString GetFullNameForDylib(ConstString basename); - virtual const char *GetDescription() = 0; + virtual llvm::StringRef GetDescription() = 0; /// Report the current status for this platform. /// @@ -243,14 +232,12 @@ public: // HostInfo::GetOSVersion(). virtual bool GetRemoteOSVersion() { return false; } - virtual bool GetRemoteOSBuildString(std::string &s) { - s.clear(); - return false; + virtual std::optional GetRemoteOSBuildString() { + return std::nullopt; } - virtual bool GetRemoteOSKernelDescription(std::string &s) { - s.clear(); - return false; + virtual std::optional GetRemoteOSKernelDescription() { + return std::nullopt; } // Remote Platform subclasses need to override this function @@ -262,7 +249,7 @@ public: virtual bool SetRemoteWorkingDirectory(const FileSpec &working_dir); - virtual UserIDResolver &GetUserIDResolver() = 0; + virtual UserIDResolver &GetUserIDResolver(); /// Locate a file for a platform. /// @@ -316,18 +303,11 @@ public: /// Get the platform's supported architectures in the order in which they /// should be searched. /// - /// \param[in] idx - /// A zero based architecture index - /// - /// \param[out] arch - /// A copy of the architecture at index if the return value is - /// \b true. - /// - /// \return - /// \b true if \a arch was filled in and is valid, \b false - /// otherwise. - virtual bool GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) = 0; + /// \param[in] process_host_arch + /// The process host architecture if it's known. An invalid ArchSpec + /// represents that the process host architecture is unknown. + virtual std::vector + GetSupportedArchitectures(const ArchSpec &process_host_arch) = 0; virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site); @@ -349,7 +329,8 @@ public: /// Lets a platform answer if it is compatible with a given architecture and /// the target triple contained within. virtual bool IsCompatibleArchitecture(const ArchSpec &arch, - bool exact_arch_match, + const ArchSpec &process_host_arch, + ArchSpec::MatchType match, ArchSpec *compatible_arch_ptr); /// Not all platforms will support debugging a process by spawning somehow @@ -363,11 +344,9 @@ public: /// platforms will want to subclass this function in order to be able to /// intercept STDIO and possibly launch a separate process that will debug /// the debuggee. - virtual lldb::ProcessSP - DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, - Target *target, // Can be nullptr, if nullptr create a new - // target, else use existing one - Status &error); + virtual lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, + Debugger &debugger, Target &target, + Status &error); virtual lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, llvm::StringRef plugin_name, @@ -512,34 +491,20 @@ public: virtual lldb::user_id_t OpenFile(const FileSpec &file_spec, File::OpenOptions flags, uint32_t mode, - Status &error) { - return UINT64_MAX; - } + Status &error); - virtual bool CloseFile(lldb::user_id_t fd, Status &error) { return false; } + virtual bool CloseFile(lldb::user_id_t fd, Status &error); - virtual lldb::user_id_t GetFileSize(const FileSpec &file_spec) { - return UINT64_MAX; - } + virtual lldb::user_id_t GetFileSize(const FileSpec &file_spec); virtual void AutoCompleteDiskFileOrDirectory(CompletionRequest &request, bool only_dir) {} virtual uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, - uint64_t dst_len, Status &error) { - error.SetErrorStringWithFormat( - "Platform::ReadFile() is not supported in the %s platform", - GetName().GetCString()); - return -1; - } + uint64_t dst_len, Status &error); virtual uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, - const void *src, uint64_t src_len, Status &error) { - error.SetErrorStringWithFormat( - "Platform::WriteFile() is not supported in the %s platform", - GetName().GetCString()); - return -1; - } + const void *src, uint64_t src_len, Status &error); virtual Status GetFile(const FileSpec &source, const FileSpec &destination); @@ -726,6 +691,24 @@ public: /// A list of symbol names. The list may be empty. virtual const std::vector &GetTrapHandlerSymbolNames(); + /// Try to get a specific unwind plan for a named trap handler. + /// The default is not to have specific unwind plans for trap handlers. + /// + /// \param[in] triple + /// Triple of the current target. + /// + /// \param[in] name + /// Name of the trap handler function. + /// + /// \return + /// A specific unwind plan for that trap handler, or an empty + /// shared pointer. The latter means there is no specific plan, + /// unwind as normal. + virtual lldb::UnwindPlanSP + GetTrapHandlerUnwindPlan(const llvm::Triple &triple, ConstString name) { + return {}; + } + /// Find a support executable that may not live within in the standard /// locations related to LLDB. /// @@ -864,7 +847,45 @@ public: return nullptr; } + /// Detect a binary in memory that will determine which Platform and + /// DynamicLoader should be used in this target/process, and update + /// the Platform/DynamicLoader. + /// The binary will be loaded into the Target, or will be registered with + /// the DynamicLoader so that it will be loaded at a later stage. Returns + /// true to indicate that this is a platform binary and has been + /// loaded/registered, no further action should be taken by the caller. + /// + /// \param[in] process + /// Process read memory from, a Process must be provided. + /// + /// \param[in] addr + /// Address of a binary in memory. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called, if a binary is loaded. + /// Caller may prefer to call ModulesDidLoad for multiple binaries + /// that were loaded at the same time. + /// + /// \return + /// Returns true if the binary was loaded in the target (or will be + /// via a DynamicLoader). Returns false if the binary was not + /// loaded/registered, and the caller must load it into the target. + virtual bool LoadPlatformBinaryAndSetup(Process *process, lldb::addr_t addr, + bool notify) { + return false; + } + + virtual CompilerType GetSiginfoType(const llvm::Triple &triple); + + virtual Args GetExtraStartupCommands(); + protected: + /// Create a list of ArchSpecs with the given OS and a architectures. The + /// vendor field is left as an "unspecified unknown". + static std::vector + CreateArchList(llvm::ArrayRef archs, + llvm::Triple::OSType os); + /// Private implementation of connecting to a process. If the stream is set /// we connect synchronously. lldb::ProcessSP DoConnectProcess(llvm::StringRef connect_url, @@ -885,7 +906,7 @@ protected: FileSpec m_working_dir; // The working directory which is used when installing // modules that have no install path set std::string m_remote_url; - std::string m_name; + std::string m_hostname; llvm::VersionTuple m_os_version; ArchSpec m_system_arch; // The architecture of the kernel or the remote platform @@ -920,8 +941,7 @@ protected: virtual void CalculateTrapHandlerSymbolNames() = 0; Status GetCachedExecutable(ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, - Platform &remote_platform); + const FileSpecList *module_search_paths_ptr); virtual Status DownloadModuleSlice(const FileSpec &src_file_spec, const uint64_t src_offset, @@ -933,6 +953,11 @@ protected: virtual const char *GetCacheHostname(); + virtual Status + ResolveRemoteExecutable(const ModuleSpec &module_spec, + lldb::ModuleSP &exe_module_sp, + const FileSpecList *module_search_paths_ptr); + private: typedef std::function ModuleResolver; @@ -944,17 +969,12 @@ private: bool GetCachedSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, bool *did_create_ptr); - Status LoadCachedExecutable(const ModuleSpec &module_spec, - lldb::ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, - Platform &remote_platform); - FileSpec GetModuleCacheRoot(); }; class PlatformList { public: - PlatformList() : m_mutex(), m_platforms(), m_selected_platform_sp() {} + PlatformList() = default; ~PlatformList() = default; @@ -1009,6 +1029,58 @@ public: } } + lldb::PlatformSP GetOrCreate(llvm::StringRef name); + lldb::PlatformSP GetOrCreate(const ArchSpec &arch, + const ArchSpec &process_host_arch, + ArchSpec *platform_arch_ptr, Status &error); + lldb::PlatformSP GetOrCreate(const ArchSpec &arch, + const ArchSpec &process_host_arch, + ArchSpec *platform_arch_ptr); + + /// Get the platform for the given list of architectures. + /// + /// The algorithm works a follows: + /// + /// 1. Returns the selected platform if it matches any of the architectures. + /// 2. Returns the host platform if it matches any of the architectures. + /// 3. Returns the platform that matches all the architectures. + /// + /// If none of the above apply, this function returns a default platform. The + /// candidates output argument differentiates between either no platforms + /// supporting the given architecture or multiple platforms supporting the + /// given architecture. + lldb::PlatformSP GetOrCreate(llvm::ArrayRef archs, + const ArchSpec &process_host_arch, + std::vector &candidates); + + lldb::PlatformSP Create(llvm::StringRef name); + + /// Detect a binary in memory that will determine which Platform and + /// DynamicLoader should be used in this target/process, and update + /// the Platform/DynamicLoader. + /// The binary will be loaded into the Target, or will be registered with + /// the DynamicLoader so that it will be loaded at a later stage. Returns + /// true to indicate that this is a platform binary and has been + /// loaded/registered, no further action should be taken by the caller. + /// + /// \param[in] process + /// Process read memory from, a Process must be provided. + /// + /// \param[in] addr + /// Address of a binary in memory. + /// + /// \param[in] notify + /// Whether ModulesDidLoad should be called, if a binary is loaded. + /// Caller may prefer to call ModulesDidLoad for multiple binaries + /// that were loaded at the same time. + /// + /// \return + /// Returns true if the binary was loaded in the target (or will be + /// via a DynamicLoader). Returns false if the binary was not + /// loaded/registered, and the caller must load it into the target. + bool LoadPlatformBinaryAndSetup(Process *process, lldb::addr_t addr, + bool notify); + protected: typedef std::vector collection; mutable std::recursive_mutex m_mutex; diff --git a/gnu/llvm/lldb/include/lldb/Target/PostMortemProcess.h b/gnu/llvm/lldb/include/lldb/Target/PostMortemProcess.h index 353bfc0919e..7207fc99ef2 100644 --- a/gnu/llvm/lldb/include/lldb/Target/PostMortemProcess.h +++ b/gnu/llvm/lldb/include/lldb/Target/PostMortemProcess.h @@ -21,9 +21,9 @@ namespace lldb_private { /// between these kinds of processes can have default implementations in this /// class. class PostMortemProcess : public Process { -public: using Process::Process; +public: bool IsLiveDebugSession() const override { return false; } }; diff --git a/gnu/llvm/lldb/include/lldb/Target/Process.h b/gnu/llvm/lldb/include/lldb/Target/Process.h index aaa2470d293..ca7f4b545e3 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Process.h +++ b/gnu/llvm/lldb/include/lldb/Target/Process.h @@ -22,10 +22,10 @@ #include #include "lldb/Breakpoint/BreakpointSiteList.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ProcessLaunchInfo.h" @@ -99,29 +99,25 @@ public: bool GetOSPluginReportsAllThreads() const; void SetOSPluginReportsAllThreads(bool does_report); bool GetSteppingRunsAllThreads() const; + FollowForkMode GetFollowForkMode() const; protected: Process *m_process; // Can be nullptr for global ProcessProperties std::unique_ptr m_experimental_properties_up; }; -typedef std::shared_ptr ProcessPropertiesSP; - // ProcessAttachInfo // // Describes any information that is required to attach to a process. class ProcessAttachInfo : public ProcessInstanceInfo { public: - ProcessAttachInfo() - : ProcessInstanceInfo(), m_listener_sp(), m_hijack_listener_sp(), - m_plugin_name() {} + ProcessAttachInfo() = default; ProcessAttachInfo(const ProcessLaunchInfo &launch_info) - : ProcessInstanceInfo(), m_listener_sp(), m_hijack_listener_sp(), - m_plugin_name(), m_resume_count(0), m_wait_for_launch(false), - m_ignore_existing(true), m_continue_once_attached(false), - m_detach_on_error(true), m_async(false) { + : m_resume_count(0), m_wait_for_launch(false), m_ignore_existing(true), + m_continue_once_attached(false), m_detach_on_error(true), + m_async(false) { ProcessInfo::operator=(launch_info); SetProcessPluginName(launch_info.GetProcessPluginName()); SetResumeCount(launch_info.GetResumeCount()); @@ -239,10 +235,11 @@ public: ~ProcessModID() = default; - void BumpStopID() { - m_stop_id++; + uint32_t BumpStopID() { + const uint32_t prev_stop_id = m_stop_id++; if (!IsLastResumeForUserExpression()) m_last_natural_stop_id++; + return prev_stop_id; } void BumpMemoryID() { m_memory_id++; } @@ -368,9 +365,6 @@ public: eBroadcastInternalStateControlResume = (1 << 2) }; - /// Process warning types. - enum Warnings { eWarningsOptimization = 1, eWarningsUnsupportedLanguage = 2 }; - typedef Range LoadRange; // We use a read/write lock to allow on or more clients to access the process // state while the process is stopped (reader). We lock the write lock to @@ -481,15 +475,6 @@ public: const ProcessEventData &operator=(const ProcessEventData &) = delete; }; - /// Construct with a shared pointer to a target, and the Process listener. - /// Uses the Host UnixSignalsSP by default. - Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - - /// Construct with a shared pointer to a target, the Process listener, and - /// the appropriate UnixSignalsSP for the process. - Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const lldb::UnixSignalsSP &unix_signals_sp); - /// Destructor. /// /// The destructor is virtual since this class is designed to be inherited @@ -500,7 +485,7 @@ public: static void SettingsTerminate(); - static const ProcessPropertiesSP &GetGlobalProperties(); + static ProcessProperties &GetGlobalProperties(); /// Find a Process plug-in that can debug \a module using the currently /// selected architecture. @@ -536,13 +521,13 @@ public: uint32_t GetAddressByteSize() const; + /// Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is + /// no known pid. + lldb::pid_t GetID() const { return m_pid; } + /// Sets the stored pid. /// /// This does not change the pid of underlying process. - lldb::pid_t GetID() const { return m_pid; } - - /// Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is - /// no known pid. void SetID(lldb::pid_t new_pid) { m_pid = new_pid; } uint32_t GetUniqueID() const { return m_process_unique_id; } @@ -611,9 +596,8 @@ public: virtual Status DoLoadCore() { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support loading core files.", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support loading core files.", GetPluginName()); return error; } @@ -657,6 +641,8 @@ public: /// plug-in. virtual DynamicLoader *GetDynamicLoader(); + void SetDynamicLoader(lldb::DynamicLoaderUP dyld); + // Returns AUXV structure found in many ELF-based environments. // // The default action is to return an empty data buffer. @@ -686,10 +672,23 @@ public: "Not implemented"); } + /// Save core dump into the specified file. + /// + /// \param[in] outfile + /// Path to store core dump in. + /// + /// \return + /// true if saved successfully, false if saving the core dump + /// is not supported by the plugin, error otherwise. + virtual llvm::Expected SaveCore(llvm::StringRef outfile); + protected: virtual JITLoaderList &GetJITLoaders(); public: + /// Get the system architecture for this process. + virtual ArchSpec GetSystemArchitecture() { return {}; } + /// Get the system runtime plug-in for this process. /// /// \return @@ -883,13 +882,28 @@ public: // Plug-in Process Control Overrides //================================================================== + /// Called before attaching to a process. + /// + /// \return + /// Returns an error object. + Status WillAttachToProcessWithID(lldb::pid_t pid); + /// Called before attaching to a process. /// /// Allow Process plug-ins to execute some code before attaching a process. /// /// \return /// Returns an error object. - virtual Status WillAttachToProcessWithID(lldb::pid_t pid) { return Status(); } + virtual Status DoWillAttachToProcessWithID(lldb::pid_t pid) { + return Status(); + } + + /// Called before attaching to a process. + /// + /// \return + /// Returns an error object. + Status WillAttachToProcessWithName(const char *process_name, + bool wait_for_launch); /// Called before attaching to a process. /// @@ -897,8 +911,8 @@ public: /// /// \return /// Returns an error object. - virtual Status WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) { + virtual Status DoWillAttachToProcessWithName(const char *process_name, + bool wait_for_launch) { return Status(); } @@ -932,9 +946,9 @@ public: virtual Status DoAttachToProcessWithID(lldb::pid_t pid, const ProcessAttachInfo &attach_info) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support attaching to a process by pid", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support attaching to a process by pid", + GetPluginName()); return error; } @@ -981,13 +995,27 @@ public: /// anything after a process exec's itself. virtual void DoDidExec() {} + /// Called after a reported fork. + virtual void DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {} + + /// Called after a reported vfork. + virtual void DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {} + + /// Called after reported vfork completion. + virtual void DidVForkDone() {} + + /// Called before launching to a process. + /// \return + /// Returns an error object. + Status WillLaunch(Module *module); + /// Called before launching to a process. /// /// Allow Process plug-ins to execute some code before launching a process. /// /// \return /// Returns an error object. - virtual Status WillLaunch(Module *module) { return Status(); } + virtual Status DoWillLaunch(Module *module) { return Status(); } /// Launch a new process. /// @@ -1008,9 +1036,8 @@ public: /// operation. virtual Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support launching processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support launching processes", GetPluginName()); return error; } @@ -1044,9 +1071,8 @@ public: /// \see Thread:Suspend() virtual Status DoResume() { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support resuming processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); return error; } @@ -1080,9 +1106,8 @@ public: /// otherwise. virtual Status DoHalt(bool &caused_stop) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support halting processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support halting processes", GetPluginName()); return error; } @@ -1107,9 +1132,9 @@ public: /// false otherwise. virtual Status DoDetach(bool keep_stopped) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support detaching from processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support detaching from processes", + GetPluginName()); return error; } @@ -1138,9 +1163,9 @@ public: /// Returns an error object. virtual Status DoSignal(int signal) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support sending signals to processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support sending signals to processes", + GetPluginName()); return error; } @@ -1296,6 +1321,15 @@ public: return StructuredData::ObjectSP(); } + // Get information about the launch state of the process, if possible. + // + // On Darwin systems, libdyld can report on process state, most importantly + // the startup stages where the system library is not yet initialized. + virtual lldb_private::StructuredData::ObjectSP + GetDynamicLoaderProcessState() { + return {}; + } + /// Print a user-visible warning about a module being built with /// optimization /// @@ -1467,36 +1501,6 @@ public: size_t ReadMemoryFromInferior(lldb::addr_t vm_addr, void *buf, size_t size, Status &error); - /// Read a NULL terminated string from memory - /// - /// This function will read a cache page at a time until a NULL string - /// terminator is found. It will stop reading if an aligned sequence of NULL - /// termination \a type_width bytes is not found before reading \a - /// cstr_max_len bytes. The results are always guaranteed to be NULL - /// terminated, and that no more than (max_bytes - type_width) bytes will be - /// read. - /// - /// \param[in] vm_addr - /// The virtual load address to start the memory read. - /// - /// \param[in] str - /// A character buffer containing at least max_bytes. - /// - /// \param[in] max_bytes - /// The maximum number of bytes to read. - /// - /// \param[in] error - /// The error status of the read operation. - /// - /// \param[in] type_width - /// The size of the null terminator (1 to 4 bytes per - /// character). Defaults to 1. - /// - /// \return - /// The error status or the number of bytes prior to the null terminator. - size_t ReadStringFromMemory(lldb::addr_t vm_addr, char *str, size_t max_bytes, - Status &error, size_t type_width = 1); - /// Read a NULL terminated C string from memory /// /// This function will read a cache page at a time until the NULL @@ -1567,9 +1571,8 @@ public: /// The number of bytes that were actually written. virtual size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Status &error) { - error.SetErrorStringWithFormat( - "error: %s does not support writing to processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support writing to processes", GetPluginName()); return 0; } @@ -1651,9 +1654,9 @@ public: virtual lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, Status &error) { - error.SetErrorStringWithFormat( - "error: %s does not support allocating in the debug process", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support allocating in the debug process", + GetPluginName()); return LLDB_INVALID_ADDRESS; } @@ -1734,8 +1737,8 @@ public: /// an error saying so. /// If it does, either the memory tags or an error describing a /// failure to read or unpack them. - llvm::Expected> ReadMemoryTags(lldb::addr_t addr, - size_t len); + virtual llvm::Expected> + ReadMemoryTags(lldb::addr_t addr, size_t len); /// Write memory tags for a range of memory. /// (calls DoWriteMemoryTags to do the target specific work) @@ -1778,7 +1781,7 @@ public: /// /// If load_addr is within the address space the process has mapped /// range_info will be filled in with the start and end of that range as - /// well as the permissions for that range and range_info.GetMapped will + /// well as the permissions for that range and range_info. GetMapped will /// return true. /// /// If load_addr is outside any mapped region then range_info will have its @@ -1787,23 +1790,21 @@ public: /// there are no valid mapped ranges between load_addr and the end of the /// process address space. /// - /// GetMemoryRegionInfo will only return an error if it is unimplemented for - /// the current process. + /// GetMemoryRegionInfo calls DoGetMemoryRegionInfo. Override that function in + /// process subclasses. /// /// \param[in] load_addr - /// The load address to query the range_info for. + /// The load address to query the range_info for. May include non + /// address bits, these will be removed by the the ABI plugin if there is + /// one. /// /// \param[out] range_info /// An range_info value containing the details of the range. /// /// \return /// An error value. - virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) { - Status error; - error.SetErrorString("Process::GetMemoryRegionInfo() not supported"); - return error; - } + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info); /// Obtain all the mapped memory regions within this process. /// @@ -1903,12 +1904,12 @@ public: /// want to deallocate. /// /// \return - /// \btrue if the memory was deallocated, \bfalse otherwise. + /// \b true if the memory was deallocated, \b false otherwise. virtual Status DoDeallocateMemory(lldb::addr_t ptr) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support deallocating in the debug process", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support deallocating in the debug process", + GetPluginName()); return error; } @@ -1922,7 +1923,7 @@ public: /// want to deallocate. /// /// \return - /// \btrue if the memory was deallocated, \bfalse otherwise. + /// \b true if the memory was deallocated, \b false otherwise. Status DeallocateMemory(lldb::addr_t ptr); /// Get any available STDOUT. @@ -2026,17 +2027,15 @@ public: virtual Status EnableBreakpointSite(BreakpointSite *bp_site) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support enabling breakpoints", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support enabling breakpoints", GetPluginName()); return error; } virtual Status DisableBreakpointSite(BreakpointSite *bp_site) { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support disabling breakpoints", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support disabling breakpoints", GetPluginName()); return error; } @@ -2117,7 +2116,7 @@ public: // Queue Queries - void UpdateQueueListIfNeeded(); + virtual void UpdateQueueListIfNeeded(); QueueList &GetQueueList() { UpdateQueueListIfNeeded(); @@ -2433,6 +2432,13 @@ void PruneThreadPlans(); return Status("Not supported"); } + /// Fetch process defined metadata. + /// + /// \return + /// A StructuredDataSP object which, if non-empty, will contain the + /// information related to the process. + virtual StructuredData::DictionarySP GetMetadata() { return nullptr; } + size_t AddImageToken(lldb::addr_t image_ptr); lldb::addr_t GetImagePtrFromToken(size_t token) const; @@ -2522,6 +2528,16 @@ void PruneThreadPlans(); protected: friend class Trace; + + /// Construct with a shared pointer to a target, and the Process listener. + /// Uses the Host UnixSignalsSP by default. + Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + + /// Construct with a shared pointer to a target, the Process listener, and + /// the appropriate UnixSignalsSP for the process. + Process(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb::UnixSignalsSP &unix_signals_sp); + /// Get the processor tracing type supported for this process. /// Responses might be different depending on the architecture and /// capabilities of the underlying OS. @@ -2625,6 +2641,26 @@ protected: virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error) = 0; + /// DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has + /// removed non address bits from load_addr. Override this method in + /// subclasses of Process. + /// + /// See GetMemoryRegionInfo for details of the logic. + /// + /// \param[in] load_addr + /// The load address to query the range_info for. (non address bits + /// removed) + /// + /// \param[out] range_info + /// An range_info value containing the details of the range. + /// + /// \return + /// An error value. + virtual Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + return Status("Process::DoGetMemoryRegionInfo() not supported"); + } + lldb::StateType GetPrivateState(); /// The "private" side of resuming a process. This doesn't alter the state @@ -2637,35 +2673,6 @@ protected: // 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 one next event // action allowed in the process at one time. If a new "NextEventAction" is @@ -2697,7 +2704,7 @@ protected: }; void SetNextEventAction(Process::NextEventAction *next_event_action) { - if (m_next_event_action_up.get()) + if (m_next_event_action_up) m_next_event_action_up->HandleBeingUnshipped(); m_next_event_action_up.reset(next_event_action); @@ -2795,9 +2802,10 @@ protected: /// if the read failed. virtual llvm::Expected> DoReadMemoryTags(lldb::addr_t addr, size_t len, int32_t type) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "%s does not support reading memory tags", - GetPluginName().GetCString()); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + llvm::formatv("{0} does not support reading memory tags", + GetPluginName())); } /// Does the final operation to write memory tags. E.g. sending a GDB packet. @@ -2820,15 +2828,15 @@ protected: /// Status telling you whether the write succeeded. virtual Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type, const std::vector &tags) { - return Status("%s does not support writing memory tags", - GetPluginName().GetCString()); + Status status; + status.SetErrorStringWithFormatv("{0} does not support writing memory tags", + GetPluginName()); + return status; } // Type definitions typedef std::map LanguageRuntimeCollection; - typedef std::unordered_set WarningsPointerSet; - typedef std::map WarningsCollection; struct PreResumeCallbackAndBaton { bool (*callback)(void *); @@ -2913,7 +2921,7 @@ protected: m_unix_signals_sp; /// This is the current signal set for this process. lldb::ABISP m_abi_sp; lldb::IOHandlerSP m_process_input_reader; - Communication m_stdio_communication; + ThreadedCommunication m_stdio_communication; std::recursive_mutex m_stdio_communication_mutex; bool m_stdin_forward; /// Remember if stdin must be forwarded to remote debug /// server @@ -2958,11 +2966,9 @@ protected: /// ShouldBroadcastEvent. 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 + bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, + // don't support the ability to modify + // the stack. std::mutex m_run_thread_plan_lock; StructuredDataPluginMap m_structured_data_plugin_map; @@ -2989,17 +2995,6 @@ protected: void ResumePrivateStateThread(); private: - struct PrivateStateThreadArgs { - PrivateStateThreadArgs(Process *p, bool s) - : process(p), is_secondary_thread(s){}; - Process *process; - bool is_secondary_thread; - }; - - // arg is a pointer to a new'ed PrivateStateThreadArgs structure. - // PrivateStateThread will free it for you. - static lldb::thread_result_t PrivateStateThread(void *arg); - // The starts up the private state thread that will watch for events from the // debugee. Pass true for is_secondary_thread in the case where you have to // temporarily spin up a secondary state thread to handle events from a hand- @@ -3073,6 +3068,9 @@ private: void ControlPrivateStateThread(uint32_t signal); + Status LaunchPrivate(ProcessLaunchInfo &launch_info, lldb::StateType &state, + lldb::EventSP &event_sp); + Process(const Process &) = delete; const Process &operator=(const Process &) = delete; }; diff --git a/gnu/llvm/lldb/include/lldb/Target/ProcessStructReader.h b/gnu/llvm/lldb/include/lldb/Target/ProcessStructReader.h index 0a91bef8048..4af51cac328 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ProcessStructReader.h +++ b/gnu/llvm/lldb/include/lldb/Target/ProcessStructReader.h @@ -39,7 +39,8 @@ protected: public: ProcessStructReader(Process *process, lldb::addr_t base_addr, - CompilerType struct_type) { + CompilerType struct_type) + : m_byte_order(lldb::eByteOrderInvalid), m_addr_byte_size(0) { if (!process) return; if (base_addr == 0 || base_addr == LLDB_INVALID_ADDRESS) @@ -69,7 +70,7 @@ public: auto total_size = struct_type.GetByteSize(nullptr); if (!total_size) return; - lldb::DataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0)); + lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0)); Status error; process->ReadMemoryFromInferior(base_addr, buffer_sp->GetBytes(), *total_size, error); diff --git a/gnu/llvm/lldb/include/lldb/Target/ProcessTrace.h b/gnu/llvm/lldb/include/lldb/Target/ProcessTrace.h index 7b9d6b13dd6..037dea232cc 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ProcessTrace.h +++ b/gnu/llvm/lldb/include/lldb/Target/ProcessTrace.h @@ -23,9 +23,9 @@ public: static void Terminate(); - static ConstString GetPluginNameStatic(); + static llvm::StringRef GetPluginNameStatic() { return "trace"; } - static const char *GetPluginDescriptionStatic(); + static llvm::StringRef GetPluginDescriptionStatic(); ProcessTrace(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); @@ -40,9 +40,7 @@ public: SystemRuntime *GetSystemRuntime() override { return nullptr; } - ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } Status DoDestroy() override; @@ -50,9 +48,8 @@ public: Status WillResume() override { Status error; - error.SetErrorStringWithFormat( - "error: %s does not support resuming processes", - GetPluginName().GetCString()); + error.SetErrorStringWithFormatv( + "error: {0} does not support resuming processes", GetPluginName()); return error; } diff --git a/gnu/llvm/lldb/include/lldb/Target/RegisterCheckpoint.h b/gnu/llvm/lldb/include/lldb/Target/RegisterCheckpoint.h index daf20db999b..bc92b239a51 100644 --- a/gnu/llvm/lldb/include/lldb/Target/RegisterCheckpoint.h +++ b/gnu/llvm/lldb/include/lldb/Target/RegisterCheckpoint.h @@ -31,17 +31,16 @@ public: eDataBackup }; - RegisterCheckpoint(Reason reason) - : UserID(0), m_data_sp(), m_reason(reason) {} + RegisterCheckpoint(Reason reason) : UserID(0), m_reason(reason) {} ~RegisterCheckpoint() = default; - lldb::DataBufferSP &GetData() { return m_data_sp; } + lldb::WritableDataBufferSP &GetData() { return m_data_sp; } - const lldb::DataBufferSP &GetData() const { return m_data_sp; } + const lldb::WritableDataBufferSP &GetData() const { return m_data_sp; } protected: - lldb::DataBufferSP m_data_sp; + lldb::WritableDataBufferSP m_data_sp; Reason m_reason; // Make RegisterCheckpointSP if you wish to share the data in this class. diff --git a/gnu/llvm/lldb/include/lldb/Target/RegisterContext.h b/gnu/llvm/lldb/include/lldb/Target/RegisterContext.h index c5068feedd5..de0efd982da 100644 --- a/gnu/llvm/lldb/include/lldb/Target/RegisterContext.h +++ b/gnu/llvm/lldb/include/lldb/Target/RegisterContext.h @@ -31,10 +31,6 @@ public: virtual const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) = 0; - // Detect the register size dynamically. - uint32_t UpdateDynamicRegisterSize(const lldb_private::ArchSpec &arch, - RegisterInfo *reg_info); - virtual size_t GetRegisterSetCount() = 0; virtual const RegisterSet *GetRegisterSet(size_t reg_set) = 0; @@ -47,7 +43,7 @@ public: virtual bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) = 0; - virtual bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) { + virtual bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) { return false; } diff --git a/gnu/llvm/lldb/include/lldb/Target/RegisterContextUnwind.h b/gnu/llvm/lldb/include/lldb/Target/RegisterContextUnwind.h index edda281d5aa..ef8ae884038 100644 --- a/gnu/llvm/lldb/include/lldb/Target/RegisterContextUnwind.h +++ b/gnu/llvm/lldb/include/lldb/Target/RegisterContextUnwind.h @@ -50,7 +50,7 @@ public: bool WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override; - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override; bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; @@ -203,8 +203,7 @@ private: void UnwindLogMsgVerbose(const char *fmt, ...) __attribute__((format(printf, 2, 3))); - bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, - int &valid_pc_offset); + bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp); lldb::addr_t GetReturnAddressHint(int32_t plan_offset); diff --git a/gnu/llvm/lldb/include/lldb/Target/RemoteAwarePlatform.h b/gnu/llvm/lldb/include/lldb/Target/RemoteAwarePlatform.h index 269d1529988..d183815e1c8 100644 --- a/gnu/llvm/lldb/include/lldb/Target/RemoteAwarePlatform.h +++ b/gnu/llvm/lldb/include/lldb/Target/RemoteAwarePlatform.h @@ -10,6 +10,7 @@ #define LLDB_TARGET_REMOTEAWAREPLATFORM_H #include "lldb/Target/Platform.h" +#include namespace lldb_private { @@ -64,8 +65,8 @@ public: FileSpec &local_file) override; bool GetRemoteOSVersion() override; - bool GetRemoteOSBuildString(std::string &s) override; - bool GetRemoteOSKernelDescription(std::string &s) override; + std::optional GetRemoteOSBuildString() override; + std::optional GetRemoteOSKernelDescription() override; ArchSpec GetRemoteSystemArchitecture() override; Status RunShellCommand(llvm::StringRef command, const FileSpec &working_dir, diff --git a/gnu/llvm/lldb/include/lldb/Target/SectionLoadHistory.h b/gnu/llvm/lldb/include/lldb/Target/SectionLoadHistory.h index dd024301d0c..64bb828d425 100644 --- a/gnu/llvm/lldb/include/lldb/Target/SectionLoadHistory.h +++ b/gnu/llvm/lldb/include/lldb/Target/SectionLoadHistory.h @@ -24,7 +24,7 @@ public: eStopIDNow = UINT32_MAX }; // Constructors and Destructors - SectionLoadHistory() : m_stop_id_to_section_load_list(), m_mutex() {} + SectionLoadHistory() = default; ~SectionLoadHistory() { // Call clear since this takes a lock and clears the section load list in diff --git a/gnu/llvm/lldb/include/lldb/Target/SectionLoadList.h b/gnu/llvm/lldb/include/lldb/Target/SectionLoadList.h index e8535e7ac51..ac86e631815 100644 --- a/gnu/llvm/lldb/include/lldb/Target/SectionLoadList.h +++ b/gnu/llvm/lldb/include/lldb/Target/SectionLoadList.h @@ -22,7 +22,7 @@ namespace lldb_private { class SectionLoadList { public: // Constructors and Destructors - SectionLoadList() : m_addr_to_sect(), m_sect_to_addr(), m_mutex() {} + SectionLoadList() = default; SectionLoadList(const SectionLoadList &rhs); diff --git a/gnu/llvm/lldb/include/lldb/Target/StackFrame.h b/gnu/llvm/lldb/include/lldb/Target/StackFrame.h index 1a9aaad1a4d..6824d916030 100644 --- a/gnu/llvm/lldb/include/lldb/Target/StackFrame.h +++ b/gnu/llvm/lldb/include/lldb/Target/StackFrame.h @@ -171,7 +171,7 @@ public: /// functions looking up symbolic information for a given pc value multiple /// times. /// - /// \params [in] resolve_scope + /// \param [in] resolve_scope /// Flags from the SymbolContextItem enumerated type which specify what /// type of symbol context is needed by this caller. /// @@ -202,7 +202,7 @@ public: /// frames may be unable to provide this value; they will return false. bool GetFrameBaseValue(Scalar &value, Status *error_ptr); - /// Get the DWARFExpression corresponding to the Canonical Frame Address. + /// Get the DWARFExpressionList corresponding to the Canonical Frame Address. /// /// Often a register (bp), but sometimes a register + offset. /// @@ -212,7 +212,7 @@ public: /// /// \return /// Returns the corresponding DWARF expression, or NULL. - DWARFExpression *GetFrameBaseExpression(Status *error_ptr); + DWARFExpressionList *GetFrameBaseExpression(Status *error_ptr); /// Get the current lexical scope block for this StackFrame, if possible. /// @@ -254,9 +254,14 @@ public: /// that are visible to the entire compilation unit (e.g. file /// static in C, globals that are homed in this CU). /// + /// \param [out] error_ptr + /// If there is an error in the debug information that prevents variables + /// from being fetched. \see SymbolFile::GetFrameVariableError() for full + /// details. + /// /// \return /// A pointer to a list of variables. - VariableList *GetVariableList(bool get_file_globals); + VariableList *GetVariableList(bool get_file_globals, Status *error_ptr); /// Retrieve the list of variables that are in scope at this StackFrame's /// pc. @@ -408,10 +413,10 @@ public: /// Create a ValueObject for a given Variable in this StackFrame. /// - /// \params [in] variable_sp + /// \param [in] variable_sp /// The Variable to base this ValueObject on /// - /// \params [in] use_dynamic + /// \param [in] use_dynamic /// Whether the correct dynamic type of the variable should be /// determined before creating the ValueObject, or if the static type /// is sufficient. One of the DynamicValueType enumerated values. @@ -437,7 +442,7 @@ public: /// the current instruction. The ExpressionPath should indicate how to get /// to this value using "frame variable." /// - /// \params [in] addr + /// \param [in] addr /// The raw address. /// /// \return @@ -448,10 +453,10 @@ public: /// given register plus an offset. The ExpressionPath should indicate how /// to get to this value using "frame variable." /// - /// \params [in] reg + /// \param [in] reg /// The name of the register. /// - /// \params [in] offset + /// \param [in] offset /// The offset from the register. Particularly important for sp... /// /// \return @@ -465,7 +470,7 @@ public: /// PC in the stack frame and traverse through all parent blocks stopping at /// inlined function boundaries. /// - /// \params [in] name + /// \param [in] name /// The name of the variable. /// /// \return diff --git a/gnu/llvm/lldb/include/lldb/Target/StackFrameList.h b/gnu/llvm/lldb/include/lldb/Target/StackFrameList.h index c98995cad36..e05a398e3c0 100644 --- a/gnu/llvm/lldb/include/lldb/Target/StackFrameList.h +++ b/gnu/llvm/lldb/include/lldb/Target/StackFrameList.h @@ -17,6 +17,8 @@ namespace lldb_private { +class ScriptedThread; + class StackFrameList { public: // Constructors and Destructors @@ -86,6 +88,7 @@ public: protected: friend class Thread; + friend class ScriptedThread; bool SetFrameAtIndex(uint32_t idx, lldb::StackFrameSP &frame_sp); diff --git a/gnu/llvm/lldb/include/lldb/Target/StackFrameRecognizer.h b/gnu/llvm/lldb/include/lldb/Target/StackFrameRecognizer.h index 64be759dc79..419f0c0aac1 100644 --- a/gnu/llvm/lldb/include/lldb/Target/StackFrameRecognizer.h +++ b/gnu/llvm/lldb/include/lldb/Target/StackFrameRecognizer.h @@ -17,6 +17,7 @@ #include "lldb/lldb-private-forward.h" #include "lldb/lldb-public.h" +#include #include namespace lldb_private { @@ -154,7 +155,7 @@ class ValueObjectRecognizerSynthesizedValue : public ValueObject { SetName(parent.GetName()); } - llvm::Optional GetByteSize() override { + std::optional GetByteSize() override { return m_parent->GetByteSize(); } lldb::ValueType GetValueType() const override { return m_type; } diff --git a/gnu/llvm/lldb/include/lldb/Target/StackID.h b/gnu/llvm/lldb/include/lldb/Target/StackID.h index 95d12df6742..09392792cb5 100644 --- a/gnu/llvm/lldb/include/lldb/Target/StackID.h +++ b/gnu/llvm/lldb/include/lldb/Target/StackID.h @@ -17,9 +17,7 @@ namespace lldb_private { class StackID { public: // Constructors and Destructors - StackID() - - {} + StackID() = default; explicit StackID(lldb::addr_t pc, lldb::addr_t cfa, SymbolContextScope *symbol_scope) diff --git a/gnu/llvm/lldb/include/lldb/Target/Statistics.h b/gnu/llvm/lldb/include/lldb/Target/Statistics.h new file mode 100644 index 00000000000..f672786f58f --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/Statistics.h @@ -0,0 +1,188 @@ +//===-- Statistics.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_STATISTICS_H +#define LLDB_TARGET_STATISTICS_H + +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Stream.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/JSON.h" +#include +#include +#include +#include +#include +#include + +namespace lldb_private { + +using StatsClock = std::chrono::high_resolution_clock; +using StatsTimepoint = std::chrono::time_point; + +class StatsDuration { +public: + using Duration = std::chrono::duration; + + Duration get() const { + return Duration(InternalDuration(value.load(std::memory_order_relaxed))); + } + operator Duration() const { return get(); } + + StatsDuration &operator+=(Duration dur) { + value.fetch_add(std::chrono::duration_cast(dur).count(), + std::memory_order_relaxed); + return *this; + } + +private: + using InternalDuration = std::chrono::duration; + std::atomic value{0}; +}; + +/// A class that measures elapsed time in an exception safe way. +/// +/// This is a RAII class is designed to help gather timing statistics within +/// LLDB where objects have optional Duration variables that get updated with +/// elapsed times. This helps LLDB measure statistics for many things that are +/// then reported in LLDB commands. +/// +/// Objects that need to measure elapsed times should have a variable of type +/// "StatsDuration m_time_xxx;" which can then be used in the constructor of +/// this class inside a scope that wants to measure something: +/// +/// ElapsedTime elapsed(m_time_xxx); +/// // Do some work +/// +/// This class will increment the m_time_xxx variable with the elapsed time +/// when the object goes out of scope. The "m_time_xxx" variable will be +/// incremented when the class goes out of scope. This allows a variable to +/// measure something that might happen in stages at different times, like +/// resolving a breakpoint each time a new shared library is loaded. +class ElapsedTime { +public: + /// Set to the start time when the object is created. + StatsTimepoint m_start_time; + /// Elapsed time in seconds to increment when this object goes out of scope. + StatsDuration &m_elapsed_time; + +public: + ElapsedTime(StatsDuration &opt_time) : m_elapsed_time(opt_time) { + m_start_time = StatsClock::now(); + } + ~ElapsedTime() { + StatsClock::duration elapsed = StatsClock::now() - m_start_time; + m_elapsed_time += elapsed; + } +}; + +/// A class to count success/fail statistics. +struct StatsSuccessFail { + StatsSuccessFail(llvm::StringRef n) : name(n.str()) {} + + void NotifySuccess() { ++successes; } + void NotifyFailure() { ++failures; } + + llvm::json::Value ToJSON() const; + std::string name; + uint32_t successes = 0; + uint32_t failures = 0; +}; + +/// A class that represents statistics for a since lldb_private::Module. +struct ModuleStats { + llvm::json::Value ToJSON() const; + intptr_t identifier; + std::string path; + std::string uuid; + std::string triple; + // Path separate debug info file, or empty if none. + std::string symfile_path; + // If the debug info is contained in multiple files where each one is + // represented as a separate lldb_private::Module, then these are the + // identifiers of these modules in the global module list. This allows us to + // track down all of the stats that contribute to this module. + std::vector symfile_modules; + llvm::StringMap type_system_stats; + double symtab_parse_time = 0.0; + double symtab_index_time = 0.0; + double debug_parse_time = 0.0; + double debug_index_time = 0.0; + uint64_t debug_info_size = 0; + bool symtab_loaded_from_cache = false; + bool symtab_saved_to_cache = false; + bool debug_info_index_loaded_from_cache = false; + bool debug_info_index_saved_to_cache = false; + bool debug_info_enabled = true; + bool symtab_stripped = false; + bool debug_info_had_variable_errors = false; + bool debug_info_had_incomplete_types = false; +}; + +struct ConstStringStats { + llvm::json::Value ToJSON() const; + ConstString::MemoryStats stats = ConstString::GetMemoryStats(); +}; + +/// A class that represents statistics for a since lldb_private::Target. +class TargetStats { +public: + llvm::json::Value ToJSON(Target &target); + + void SetLaunchOrAttachTime(); + void SetFirstPrivateStopTime(); + void SetFirstPublicStopTime(); + void IncreaseSourceMapDeduceCount(); + + StatsDuration &GetCreateTime() { return m_create_time; } + StatsSuccessFail &GetExpressionStats() { return m_expr_eval; } + StatsSuccessFail &GetFrameVariableStats() { return m_frame_var; } + +protected: + StatsDuration m_create_time; + std::optional m_launch_or_attach_time; + std::optional m_first_private_stop_time; + std::optional m_first_public_stop_time; + StatsSuccessFail m_expr_eval{"expressionEvaluation"}; + StatsSuccessFail m_frame_var{"frameVariable"}; + std::vector m_module_identifiers; + uint32_t m_source_map_deduce_count = 0; + void CollectStats(Target &target); +}; + +class DebuggerStats { +public: + static void SetCollectingStats(bool enable) { g_collecting_stats = enable; } + static bool GetCollectingStats() { return g_collecting_stats; } + + /// Get metrics associated with one or all targets in a debugger in JSON + /// format. + /// + /// \param debugger + /// The debugger to get the target list from if \a target is NULL. + /// + /// \param target + /// The single target to emit statistics for if non NULL, otherwise dump + /// statistics only for the specified target. + /// + /// \return + /// Returns a JSON value that contains all target metrics. + static llvm::json::Value ReportStatistics(Debugger &debugger, Target *target); + +protected: + // Collecting stats can be set to true to collect stats that are expensive + // to collect. By default all stats that are cheap to collect are enabled. + // This settings is here to maintain compatibility with "statistics enable" + // and "statistics disable". + static bool g_collecting_stats; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_STATISTICS_H diff --git a/gnu/llvm/lldb/include/lldb/Target/StopInfo.h b/gnu/llvm/lldb/include/lldb/Target/StopInfo.h index 0e81e516084..9527a6ea553 100644 --- a/gnu/llvm/lldb/include/lldb/Target/StopInfo.h +++ b/gnu/llvm/lldb/include/lldb/Target/StopInfo.h @@ -17,7 +17,7 @@ namespace lldb_private { -class StopInfo { +class StopInfo : public std::enable_shared_from_this { friend class Process::ProcessEventData; friend class ThreadPlanBase; @@ -132,6 +132,16 @@ public: static lldb::StopInfoSP CreateStopReasonProcessorTrace(Thread &thread, const char *description); + static lldb::StopInfoSP CreateStopReasonFork(Thread &thread, + lldb::pid_t child_pid, + lldb::tid_t child_tid); + + static lldb::StopInfoSP CreateStopReasonVFork(Thread &thread, + lldb::pid_t child_pid, + lldb::tid_t child_tid); + + static lldb::StopInfoSP CreateStopReasonVForkDone(Thread &thread); + static lldb::ValueObjectSP GetReturnValueObject(lldb::StopInfoSP &stop_info_sp); diff --git a/gnu/llvm/lldb/include/lldb/Target/SystemRuntime.h b/gnu/llvm/lldb/include/lldb/Target/SystemRuntime.h index 0ec0793e95f..66868e474c6 100644 --- a/gnu/llvm/lldb/include/lldb/Target/SystemRuntime.h +++ b/gnu/llvm/lldb/include/lldb/Target/SystemRuntime.h @@ -77,7 +77,7 @@ public: /// /// Allow the SystemRuntime plugin to enable logging features in the system /// runtime libraries. - virtual void ModulesDidLoad(const ModuleList &module_list) override; + void ModulesDidLoad(const ModuleList &module_list) override; /// Called before detaching from a process. /// diff --git a/gnu/llvm/lldb/include/lldb/Target/Target.h b/gnu/llvm/lldb/include/lldb/Target/Target.h index ac8d002b09a..09fbf45191d 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Target.h +++ b/gnu/llvm/lldb/include/lldb/Target/Target.h @@ -21,6 +21,7 @@ #include "lldb/Core/Architecture.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/ModuleList.h" +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Expression/Expression.h" #include "lldb/Host/ProcessLaunchInfo.h" @@ -28,6 +29,7 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/PathMappingList.h" #include "lldb/Target/SectionLoadHistory.h" +#include "lldb/Target/Statistics.h" #include "lldb/Target/ThreadSpec.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Broadcaster.h" @@ -57,18 +59,19 @@ enum LoadCWDlldbinitFile { eLoadCWDlldbinitWarn }; -enum LoadDependentFiles { - eLoadDependentsDefault, - eLoadDependentsYes, - eLoadDependentsNo, -}; - enum ImportStdModule { eImportStdModuleFalse, eImportStdModuleFallback, eImportStdModuleTrue, }; +enum DynamicClassInfoHelper { + eDynamicClassInfoHelperAuto, + eDynamicClassInfoHelperRealizedClassesStruct, + eDynamicClassInfoHelperCopyRealizedClassList, + eDynamicClassInfoHelperGetRealizedClassList, +}; + class TargetExperimentalProperties : public Properties { public: TargetExperimentalProperties(); @@ -122,13 +125,24 @@ public: void SetRunArguments(const Args &args); + // Get the whole environment including the platform inherited environment and + // the target specific environment, excluding the unset environment variables. Environment GetEnvironment() const; + // Get the platform inherited environment, excluding the unset environment + // variables. + Environment GetInheritedEnvironment() const; + // Get the target specific environment only, without the platform inherited + // environment. + Environment GetTargetEnvironment() const; + // Set the target specific environment. void SetEnvironment(Environment env); bool GetSkipPrologue() const; PathMappingList &GetSourcePathMap() const; + bool GetAutoSourceMapRelative() const; + FileSpecList GetExecutableSearchPaths(); void AppendExecutableSearchPaths(const FileSpec &); @@ -141,13 +155,15 @@ public: ImportStdModule GetImportStdModule() const; + DynamicClassInfoHelper GetDynamicClassInfoHelper() const; + bool GetEnableAutoApplyFixIts() const; uint64_t GetNumberOfRetriesWithFixits() const; bool GetEnableNotifyAboutFixIts() const; - bool GetEnableSaveObjects() const; + FileSpec GetSaveJITObjectsDir() const; bool GetEnableSyntheticValue() const; @@ -155,6 +171,15 @@ public: uint32_t GetMaximumNumberOfChildrenToDisplay() const; + /// Get the max depth value, augmented with a bool to indicate whether the + /// depth is the default. + /// + /// When the user has customized the max depth, the bool will be false. + /// + /// \returns the max depth, and true if the max depth is the system default, + /// otherwise false. + std::pair GetMaximumDepthOfChildrenToDisplay() const; + uint32_t GetMaximumSizeOfStringSummary() const; uint32_t GetMaximumMemReadSize() const; @@ -197,10 +222,6 @@ public: void SetUserSpecifiedTrapHandlerNames(const Args &args); - bool GetNonStopModeEnabled() const; - - void SetNonStopModeEnabled(bool b); - bool GetDisplayRuntimeSupportValues() const; void SetDisplayRuntimeSupportValues(bool b); @@ -242,6 +263,9 @@ private: void InheritTCCValueChangedCallback(); void DisableSTDIOValueChangedCallback(); + // Settings checker for target.jit-save-objects-dir: + void CheckJITObjectsDir(); + Environment ComputeEnvironment() const; // Member variables. @@ -431,14 +455,14 @@ private: lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues; Timeout m_timeout = default_timeout; - Timeout m_one_thread_timeout = llvm::None; + Timeout m_one_thread_timeout = std::nullopt; lldb::ExpressionCancelCallback m_cancel_callback = nullptr; void *m_cancel_callback_baton = nullptr; // 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; + mutable uint32_t m_pound_line_line = 0; }; // Target @@ -457,7 +481,8 @@ public: eBroadcastBitModulesLoaded = (1 << 1), eBroadcastBitModulesUnloaded = (1 << 2), eBroadcastBitWatchpointChanged = (1 << 3), - eBroadcastBitSymbolsLoaded = (1 << 4) + eBroadcastBitSymbolsLoaded = (1 << 4), + eBroadcastBitSymbolsChanged = (1 << 5), }; // These two functions fill out the Broadcaster interface: @@ -557,7 +582,7 @@ public: // Settings accessors - static const lldb::TargetPropertiesSP &GetGlobalProperties(); + static TargetProperties &GetGlobalProperties(); std::recursive_mutex &GetAPIMutex(); @@ -732,8 +757,7 @@ public: const BreakpointName::Permissions &permissions); void ApplyNameToBreakpoints(BreakpointName &bp_name); - // This takes ownership of the name obj passed in. - void AddBreakpointName(BreakpointName *bp_name); + void AddBreakpointName(std::unique_ptr bp_name); void GetBreakpointNames(std::vector &names); @@ -757,6 +781,9 @@ public: bool RemoveBreakpointByID(lldb::break_id_t break_id); + /// Resets the hit count of all breakpoints. + void ResetBreakpointHitCounts(); + // The flag 'end_to_end', default to true, signifies that the operation is // performed end to end, for both the debugger and the debuggee. @@ -960,6 +987,9 @@ public: const ArchSpec &GetArchitecture() const { return m_arch.GetSpec(); } + /// Returns the name of the target's ABI plugin. + llvm::StringRef GetABIName() const; + /// Set the architecture for this target. /// /// If the current target has no Images read in, then this just sets the @@ -983,9 +1013,14 @@ public: /// currently selected platform isn't compatible (in case it might be /// manually set following this function call). /// + /// \param[in] merged + /// If true, arch_spec is merged with the current + /// architecture. Otherwise it's replaced. + /// /// \return - /// \b true if the architecture was successfully set, \bfalse otherwise. - bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false); + /// \b true if the architecture was successfully set, \b false otherwise. + bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false, + bool merge = true); bool MergeArchitecture(const ArchSpec &arch_spec); @@ -1012,10 +1047,42 @@ public: lldb::addr_t *load_addr_ptr = nullptr); size_t ReadCStringFromMemory(const Address &addr, std::string &out_str, - Status &error); + Status &error, bool force_live_memory = false); size_t ReadCStringFromMemory(const Address &addr, char *dst, - size_t dst_max_len, Status &result_error); + size_t dst_max_len, Status &result_error, + bool force_live_memory = false); + + /// Read a NULL terminated string from memory + /// + /// This function will read a cache page at a time until a NULL string + /// terminator is found. It will stop reading if an aligned sequence of NULL + /// termination \a type_width bytes is not found before reading \a + /// cstr_max_len bytes. The results are always guaranteed to be NULL + /// terminated, and that no more than (max_bytes - type_width) bytes will be + /// read. + /// + /// \param[in] addr + /// The address to start the memory read. + /// + /// \param[in] dst + /// A character buffer containing at least max_bytes. + /// + /// \param[in] max_bytes + /// The maximum number of bytes to read. + /// + /// \param[in] error + /// The error status of the read operation. + /// + /// \param[in] type_width + /// The size of the null terminator (1 to 4 bytes per + /// character). Defaults to 1. + /// + /// \return + /// The error status or the number of bytes prior to the null terminator. + size_t ReadStringFromMemory(const Address &addr, char *dst, size_t max_bytes, + Status &error, size_t type_width, + bool force_live_memory = true); size_t ReadScalarIntegerFromMemory(const Address &addr, uint32_t byte_size, bool is_signed, Scalar &scalar, @@ -1051,11 +1118,12 @@ public: PathMappingList &GetImageSearchPathList(); - llvm::Expected + llvm::Expected GetScratchTypeSystemForLanguage(lldb::LanguageType language, bool create_on_demand = true); - std::vector GetScratchTypeSystems(bool create_on_demand = true); + std::vector + GetScratchTypeSystems(bool create_on_demand = true); PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language); @@ -1235,7 +1303,7 @@ public: class StopHookCommandLine : public StopHook { public: - virtual ~StopHookCommandLine() = default; + ~StopHookCommandLine() override = default; StringList &GetCommands() { return m_commands; } void SetActionFromString(const std::string &strings); @@ -1258,7 +1326,7 @@ public: class StopHookScripted : public StopHook { public: - virtual ~StopHookScripted() = default; + ~StopHookScripted() override = default; StopHookResult HandleStop(ExecutionContext &exc_ctx, lldb::StreamSP output) override; @@ -1272,8 +1340,7 @@ public: std::string m_class_name; /// This holds the dictionary of keys & values that can be used to /// parametrize any given callback's behavior. - StructuredDataImpl *m_extra_args; // We own this structured data, - // but the SD itself manages the UP. + StructuredDataImpl m_extra_args; /// This holds the python callback object. StructuredData::GenericSP m_implementation_sp; @@ -1361,6 +1428,42 @@ public: return *m_frame_recognizer_manager_up; } + /// Add a signal for the target. This will get copied over to the process + /// if the signal exists on that target. Only the values with Yes and No are + /// set, Calculate values will be ignored. +protected: + struct DummySignalValues { + LazyBool pass = eLazyBoolCalculate; + LazyBool notify = eLazyBoolCalculate; + LazyBool stop = eLazyBoolCalculate; + DummySignalValues(LazyBool pass, LazyBool notify, LazyBool stop) + : pass(pass), notify(notify), stop(stop) {} + DummySignalValues() = default; + }; + using DummySignalElement = llvm::StringMapEntry; + static bool UpdateSignalFromDummy(lldb::UnixSignalsSP signals_sp, + const DummySignalElement &element); + static bool ResetSignalFromDummy(lldb::UnixSignalsSP signals_sp, + const DummySignalElement &element); + +public: + /// Add a signal to the Target's list of stored signals/actions. These + /// values will get copied into any processes launched from + /// this target. + void AddDummySignal(llvm::StringRef name, LazyBool pass, LazyBool print, + LazyBool stop); + /// Updates the signals in signals_sp using the stored dummy signals. + /// If warning_stream_sp is not null, if any stored signals are not found in + /// the current process, a warning will be emitted here. + void UpdateSignalsFromDummy(lldb::UnixSignalsSP signals_sp, + lldb::StreamSP warning_stream_sp); + /// Clear the dummy signals in signal_names from the target, or all signals + /// if signal_names is empty. Also remove the behaviors they set from the + /// process's signals if it exists. + void ClearDummySignals(Args &signal_names); + /// Print all the signals set in this target. + void PrintDummySignals(Stream &strm, Args &signals); + protected: /// Implementing of ModuleList::Notifier. @@ -1390,6 +1493,7 @@ protected: ArchSpec m_spec; std::unique_ptr m_plugin_up; }; + // Member variables. Debugger &m_debugger; lldb::PlatformSP m_platform_sp; ///< The platform for this target. @@ -1407,7 +1511,8 @@ protected: SectionLoadHistory m_section_load_history; BreakpointList m_breakpoint_list; BreakpointList m_internal_breakpoint_list; - using BreakpointNameList = std::map; + using BreakpointNameList = + std::map>; BreakpointNameList m_breakpoint_names; lldb::BreakpointSP m_last_created_breakpoint; @@ -1440,29 +1545,32 @@ protected: lldb::TraceSP m_trace_sp; /// Stores the frame recognizers of this target. lldb::StackFrameRecognizerManagerUP m_frame_recognizer_manager_up; + /// These are used to set the signal state when you don't have a process and + /// more usefully in the Dummy target where you can't know exactly what + /// signals you will have. + llvm::StringMap m_dummy_signals; static void ImageSearchPathsChanged(const PathMappingList &path_list, void *baton); // Utilities for `statistics` command. private: - std::vector m_stats_storage; - bool m_collecting_stats = false; + // Target metrics storage. + TargetStats m_stats; public: - void SetCollectingStats(bool v) { m_collecting_stats = v; } - - bool GetCollectingStats() { return m_collecting_stats; } - - void IncrementStats(lldb_private::StatisticKind key) { - if (!GetCollectingStats()) - return; - lldbassert(key < lldb_private::StatisticKind::StatisticMax && - "invalid statistics!"); - m_stats_storage[key] += 1; - } + /// Get metrics associated with this target in JSON format. + /// + /// Target metrics help measure timings and information that is contained in + /// a target. These are designed to help measure performance of a debug + /// session as well as represent the current state of the target, like + /// information on the currently modules, currently set breakpoints and more. + /// + /// \return + /// Returns a JSON value that contains all target metrics. + llvm::json::Value ReportStatistics(); - std::vector GetStatistics() { return m_stats_storage; } + TargetStats &GetStatistics() { return m_stats; } private: /// Construct with optional file and arch. @@ -1485,6 +1593,10 @@ private: void FinalizeFileActions(ProcessLaunchInfo &info); + /// Return a recommended size for memory reads at \a addr, optimizing for + /// cache usage. + lldb::addr_t GetReasonableReadSize(const Address &addr); + Target(const Target &) = delete; const Target &operator=(const Target &) = delete; }; diff --git a/gnu/llvm/lldb/include/lldb/Target/Thread.h b/gnu/llvm/lldb/include/lldb/Target/Thread.h index 0f6b5741573..efe82721a04 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Thread.h +++ b/gnu/llvm/lldb/include/lldb/Target/Thread.h @@ -22,6 +22,7 @@ #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/UnimplementedError.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" @@ -57,8 +58,6 @@ public: uint64_t GetMaxBacktraceDepth() const; }; -typedef std::shared_ptr ThreadPropertiesSP; - class Thread : public std::enable_shared_from_this, public ThreadProperties, public UserID, @@ -149,7 +148,7 @@ public: static void SettingsTerminate(); - static const ThreadPropertiesSP &GetGlobalProperties(); + static ThreadProperties &GetGlobalProperties(); lldb::ProcessSP GetProcess() const { return m_process_wp.lock(); } @@ -241,6 +240,7 @@ public: // this just calls through to the ThreadSpec's ThreadPassesBasicTests method. virtual bool MatchesSpec(const ThreadSpec *spec); + // Get the current public stop info, calculating it if necessary. lldb::StopInfoSP GetStopInfo(); lldb::StopReason GetStopReason(); @@ -540,9 +540,12 @@ public: /// This function is designed to be used by commands where the /// process is publicly stopped. /// + /// \param[in] frame_idx + /// The frame index to step out of. + /// /// \return /// An error that describes anything that went wrong - virtual Status StepOut(); + virtual Status StepOut(uint32_t frame_idx = 0); /// Retrieves the per-thread data area. /// Most OSs maintain a per-thread pointer (e.g. the FS register on @@ -837,7 +840,7 @@ public: /// See standard meanings for the stop & run votes in ThreadPlan.h. /// /// \param[in] frame_idx - /// The fame index. + /// The frame index. /// /// \param[out] status /// A status with an error if queuing failed. @@ -1017,7 +1020,8 @@ public: /// Discards the plans queued on the plan stack of the current thread. This /// is - /// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call. + /// arbitrated by the "Controlling" ThreadPlans, using the "OkayToDiscard" + /// call. // But if \a force is true, all thread plans are discarded. void DiscardThreadPlans(bool force); @@ -1118,7 +1122,7 @@ public: // "checkpointed and restored" stop info, so if it is still around it is // right even if you have not calculated this yourself, or if it disagrees // with what you might have calculated. - virtual lldb::StopInfoSP GetPrivateStopInfo(); + virtual lldb::StopInfoSP GetPrivateStopInfo(bool calculate = true); // Calculate the stop info that will be shown to lldb clients. For instance, // a "step out" is implemented by running to a breakpoint on the function @@ -1162,6 +1166,14 @@ public: void ResetStopInfo(); void SetShouldReportStop(Vote vote); + + void SetShouldRunBeforePublicStop(bool newval) { + m_should_run_before_public_stop = newval; + } + + bool ShouldRunBeforePublicStop() { + return m_should_run_before_public_stop; + } /// Sets the extended backtrace token for this thread /// @@ -1185,6 +1197,8 @@ public: lldb::ThreadSP GetCurrentExceptionBacktrace(); + lldb::ValueObjectSP GetSiginfoValue(); + protected: friend class ThreadPlan; friend class ThreadList; @@ -1234,6 +1248,11 @@ protected: void FrameSelectedCallback(lldb_private::StackFrame *frame); + virtual llvm::Expected> + GetSiginfo(size_t max_size) const { + return llvm::make_error(); + } + // Classes that inherit from Process can see and modify these lldb::ProcessWP m_process_wp; ///< The process that owns this thread. lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread @@ -1244,8 +1263,11 @@ protected: uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time // the stop info was checked against // the stop info override + bool m_should_run_before_public_stop; // If this thread has "stop others" + // private work to do, then it will + // set this. const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread - ///for easy UI/command line access. + /// for easy UI/command line access. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this ///thread's current register state. lldb::StateType m_state; ///< The state of our process. diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlan.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlan.h index 5e14a1fd657..bf68a42e54d 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlan.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlan.h @@ -81,7 +81,7 @@ namespace lldb_private { // // Cleaning up after your plans: // -// When the plan is moved from the plan stack its WillPop method is always +// When the plan is moved from the plan stack its DidPop method is always // called, no matter why. Once it is moved off the plan stack it is done, and // won't get a chance to run again. So you should undo anything that affects // target state in this method. But be sure to leave the plan able to @@ -144,39 +144,42 @@ namespace lldb_private { // implement DoPlanExplainsStop, the result is cached in PlanExplainsStop so // the DoPlanExplainsStop itself will only get called once per stop. // -// Master plans: +// Controlling plans: // // In the normal case, when we decide to stop, we will collapse the plan // stack up to the point of the plan that understood the stop reason. // However, if a plan wishes to stay on the stack after an event it didn't -// directly handle it can designate itself a "Master" plan by responding true -// to IsMasterPlan, and then if it wants not to be discarded, it can return -// false to OkayToDiscard, and it and all its dependent plans will be +// directly handle it can designate itself a "Controlling" plan by responding +// true to IsControllingPlan, and then if it wants not to be discarded, it can +// return false to OkayToDiscard, and it and all its dependent plans will be // preserved when we resume execution. // -// The other effect of being a master plan is that when the Master plan is +// The other effect of being a controlling plan is that when the Controlling +// plan is // done , if it has set "OkayToDiscard" to false, then it will be popped & // execution will stop and return to the user. Remember that if OkayToDiscard // is false, the plan will be popped and control will be given to the next // plan above it on the stack So setting OkayToDiscard to false means the -// user will regain control when the MasterPlan is completed. +// user will regain control when the ControllingPlan is completed. // // Between these two controls this allows things like: a -// MasterPlan/DontDiscard Step Over to hit a breakpoint, stop and return +// ControllingPlan/DontDiscard Step Over to hit a breakpoint, stop and return // control to the user, but then when the user continues, the step out // succeeds. Even more tricky, when the breakpoint is hit, the user can // continue to step in/step over/etc, and finally when they continue, they // will finish up the Step Over. // -// FIXME: MasterPlan & OkayToDiscard aren't really orthogonal. MasterPlan +// FIXME: ControllingPlan & OkayToDiscard aren't really orthogonal. +// ControllingPlan // designation means that this plan controls it's fate and the fate of plans -// below it. OkayToDiscard tells whether the MasterPlan wants to stay on the -// stack. I originally thought "MasterPlan-ness" would need to be a fixed +// below it. OkayToDiscard tells whether the ControllingPlan wants to stay on +// the stack. I originally thought "ControllingPlan-ness" would need to be a +// fixed // characteristic of a ThreadPlan, in which case you needed the extra control. // But that doesn't seem to be true. So we should be able to convert to only -// MasterPlan status to mean the current "MasterPlan/DontDiscard". Then no -// plans would be MasterPlans by default, and you would set the ones you -// wanted to be "user level" in this way. +// ControllingPlan status to mean the current "ControllingPlan/DontDiscard". +// Then no plans would be ControllingPlans by default, and you would set the +// ones you wanted to be "user level" in this way. // // // Actually Stopping: @@ -224,9 +227,11 @@ namespace lldb_private { // // Cleaning up the plan stack: // -// One of the complications of MasterPlans is that you may get past the limits +// One of the complications of ControllingPlans is that you may get past the +// limits // of a plan without triggering it to clean itself up. For instance, if you -// are doing a MasterPlan StepOver, and hit a breakpoint in a called function, +// are doing a ControllingPlan StepOver, and hit a breakpoint in a called +// function, // then step over enough times to step out of the initial StepOver range, each // of the step overs will explain the stop & take themselves off the stack, // but control would never be returned to the original StepOver. Eventually, @@ -379,6 +384,8 @@ public: virtual void SetStopOthers(bool new_value); virtual bool StopOthers(); + + virtual bool ShouldRunBeforePublicStop() { return false; } // This is the wrapper for DoWillResume that does generic ThreadPlan logic, // then calls DoWillResume. @@ -386,11 +393,11 @@ public: virtual bool WillStop() = 0; - bool IsMasterPlan() { return m_is_master_plan; } + bool IsControllingPlan() { return m_is_controlling_plan; } - bool SetIsMasterPlan(bool value) { - bool old_value = m_is_master_plan; - m_is_master_plan = value; + bool SetIsControllingPlan(bool value) { + bool old_value = m_is_controlling_plan; + m_is_controlling_plan = value; return old_value; } @@ -413,7 +420,7 @@ public: virtual void DidPush(); - virtual void WillPop(); + virtual void DidPop(); ThreadPlanKind GetKind() const { return m_kind; } @@ -490,12 +497,12 @@ protected: virtual bool DoPlanExplainsStop(Event *event_ptr) = 0; // This pushes a plan onto the plan stack of the current plan's thread. - // Also sets the plans to private and not master plans. A plan pushed by + // Also sets the plans to private and not controlling plans. A plan pushed by // another thread plan is never either of the above. void PushPlan(lldb::ThreadPlanSP &thread_plan_sp) { GetThread().PushPlan(thread_plan_sp); thread_plan_sp->SetPrivate(true); - thread_plan_sp->SetIsMasterPlan(false); + thread_plan_sp->SetIsControllingPlan(false); } // This gets the previous plan to the current plan (for forwarding requests). @@ -546,7 +553,7 @@ private: bool m_plan_complete; bool m_plan_private; bool m_okay_to_discard; - bool m_is_master_plan; + bool m_is_controlling_plan; bool m_plan_succeeded; lldb::ThreadPlanTracerSP m_tracer_sp; diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallFunction.h index 24c5736f44c..cb6e7caebb4 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -68,10 +68,10 @@ public: // been cleaned up. lldb::addr_t GetFunctionStackPointer() { return m_function_sp; } - // Classes that derive from FunctionCaller, and implement their own WillPop + // Classes that derive from FunctionCaller, and implement their own DidPop // methods should call this so that the thread state gets restored if the // plan gets discarded. - void WillPop() override; + void DidPop() 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 diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h index adaea6c7056..11e126a2da9 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -32,7 +32,7 @@ public: void DidPush() override; - void WillPop() override; + void DidPop() override; lldb::StopInfoSP GetRealStopInfo() override; diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanPython.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanPython.h index 7b37b2b9ce5..f148f88d4c4 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanPython.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanPython.h @@ -12,8 +12,7 @@ #include -#include "lldb/lldb-forward.h" - +#include "lldb/Core/StructuredDataImpl.h" #include "lldb/Target/Process.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" @@ -22,6 +21,7 @@ #include "lldb/Target/ThreadPlanTracer.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/UserID.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" namespace lldb_private { @@ -31,9 +31,8 @@ namespace lldb_private { class ThreadPlanPython : public ThreadPlan { public: - ThreadPlanPython(Thread &thread, const char *class_name, - StructuredDataImpl *args_data); - ~ThreadPlanPython() override; + ThreadPlanPython(Thread &thread, const char *class_name, + const StructuredDataImpl &args_data); void GetDescription(Stream *s, lldb::DescriptionLevel level) override; @@ -62,10 +61,7 @@ protected: private: std::string m_class_name; - StructuredDataImpl *m_args_data; // We own this, but the implementation - // has to manage the UP (since that is - // how it gets stored in the - // SBStructuredData). + StructuredDataImpl m_args_data; std::string m_error_str; StructuredData::ObjectSP m_implementation_sp; bool m_did_push; diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStack.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStack.h index e0f76f8e1df..e6a560a5092 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStack.h @@ -60,7 +60,7 @@ public: void DiscardAllPlans(); - void DiscardConsultingMasterPlans(); + void DiscardConsultingControllingPlans(); lldb::ThreadPlanSP GetCurrentPlan() const; @@ -123,11 +123,13 @@ public: bool check_for_new = true); void AddThread(Thread &thread) { + std::lock_guard guard(m_stack_map_mutex); lldb::tid_t tid = thread.GetID(); m_plans_list.emplace(tid, thread); } bool RemoveTID(lldb::tid_t tid) { + std::lock_guard guard(m_stack_map_mutex); auto result = m_plans_list.find(tid); if (result == m_plans_list.end()) return false; @@ -137,6 +139,7 @@ public: } ThreadPlanStack *Find(lldb::tid_t tid) { + std::lock_guard guard(m_stack_map_mutex); auto result = m_plans_list.find(tid); if (result == m_plans_list.end()) return nullptr; @@ -154,6 +157,7 @@ public: } void Clear() { + std::lock_guard guard(m_stack_map_mutex); for (auto &plan : m_plans_list) plan.second.ThreadDestroyed(nullptr); m_plans_list.clear(); @@ -172,8 +176,10 @@ public: private: Process &m_process; + mutable std::recursive_mutex m_stack_map_mutex; using PlansList = std::unordered_map; PlansList m_plans_list; + }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h index 86f7798487c..1f3aff45c49 100644 --- a/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h +++ b/gnu/llvm/lldb/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -26,7 +26,7 @@ public: bool StopOthers() override; lldb::StateType GetPlanRunState() override; bool WillStop() override; - void WillPop() override; + void DidPop() override; bool MischiefManaged() override; void ThreadDestroyed() override; void SetAutoContinue(bool do_it); diff --git a/gnu/llvm/lldb/include/lldb/Target/Trace.h b/gnu/llvm/lldb/include/lldb/Target/Trace.h index f5654988b20..fc67a0e05ab 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Trace.h +++ b/gnu/llvm/lldb/include/lldb/Target/Trace.h @@ -9,6 +9,7 @@ #ifndef LLDB_TARGET_TRACE_H #define LLDB_TARGET_TRACE_H +#include #include #include "llvm/Support/JSON.h" @@ -20,6 +21,7 @@ #include "lldb/Utility/TraceGDBRemotePackets.h" #include "lldb/Utility/UnimplementedError.h" #include "lldb/lldb-private.h" +#include "lldb/lldb-types.h" namespace lldb_private { @@ -55,6 +57,25 @@ public: /// A stream object to dump the information to. virtual void Dump(Stream *s) const = 0; + /// Save the trace to the specified directory, which will be created if + /// needed. This will also create a a file \a /trace.json with the + /// main properties of the trace session, along with others files which + /// contain the actual trace data. The trace.json file can be used later as + /// input for the "trace load" command to load the trace in LLDB. + /// + /// \param[in] directory + /// The directory where the trace files will be saved. + /// + /// \param[in] compact + /// Try not to save to disk information irrelevant to the traced processes. + /// Each trace plug-in implements this in a different fashion. + /// + /// \return + /// A \a FileSpec pointing to the bundle description file, or an \a + /// llvm::Error otherwise. + virtual llvm::Expected SaveToDisk(FileSpec directory, + bool compact) = 0; + /// Find a trace plug-in using JSON data. /// /// When loading trace data from disk, the information for the trace data @@ -65,7 +86,7 @@ public: /// - The plug-in name (this allows a specific plug-in to be selected) /// - Architecture or target triple /// - one or more paths to the trace data file on disk - /// - core trace data + /// - cpu trace data /// - thread events or related information /// - shared library load information to use for this trace data that /// allows a target to be created so the trace information can be @@ -85,17 +106,14 @@ public: /// The debugger instance where new Targets will be created as part of the /// JSON data parsing. /// - /// \param[in] trace_session_file - /// The contents of the trace session file describing the trace session. - /// See \a TraceSessionFileParser::BuildSchema for more information about - /// the schema of this JSON file. + /// \param[in] bundle_description + /// The trace bundle description object describing the trace session. /// - /// \param[in] session_file_dir - /// The path to the directory that contains the session file. It's used to - /// resolved relative paths in the session file. + /// \param[in] bundle_dir + /// The path to the directory that contains the trace bundle. static llvm::Expected FindPluginForPostMortemProcess(Debugger &debugger, - const llvm::json::Value &trace_session_file, + const llvm::json::Value &bundle_description, llvm::StringRef session_file_dir); /// Find a trace plug-in to trace a live process. @@ -120,6 +138,23 @@ public: static llvm::Expected FindPluginSchema(llvm::StringRef plugin_name); + /// Load a trace from a trace description file and create Targets, + /// Processes and Threads based on the contents of such file. + /// + /// \param[in] debugger + /// The debugger instance where new Targets will be created as part of the + /// JSON data parsing. + /// + /// \param[in] trace_description_file + /// The file containing the necessary information to load the trace. + /// + /// \return + /// A \a TraceSP instance, or an \a llvm::Error if loading the trace + /// fails. + static llvm::Expected + LoadPostMortemTraceFromFile(Debugger &debugger, + const FileSpec &trace_description_file); + /// Get the command handle for the "process trace start" command. virtual lldb::CommandObjectSP GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0; @@ -135,10 +170,10 @@ public: /// Get a \a TraceCursor for the given thread's trace. /// /// \return - /// A \a TraceCursorUP. If the thread is not traced or its trace - /// information failed to load, the corresponding error is embedded in the - /// trace. - virtual lldb::TraceCursorUP GetCursor(Thread &thread) = 0; + /// A \a TraceCursorSP. If the thread is not traced or its trace + /// information failed to load, an \a llvm::Error is returned. + virtual llvm::Expected + CreateNewCursor(Thread &thread) = 0; /// Dump general info about a given thread's trace. Each Trace plug-in /// decides which data to show. @@ -152,16 +187,17 @@ public: /// \param[in] verbose /// If \b true, print detailed info /// If \b false, print compact info - virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) = 0; + virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, + bool json) = 0; /// Check if a thread is currently traced by this object. /// - /// \param[in] thread - /// The thread in question. + /// \param[in] tid + /// The id of the thread in question. /// /// \return /// \b true if the thread is traced by this instance, \b false otherwise. - virtual bool IsTraced(const Thread &thread) = 0; + virtual bool IsTraced(lldb::tid_t tid) = 0; /// \return /// A description of the parameters to use for the \a Trace::Start method. @@ -216,15 +252,179 @@ public: /// \a llvm::Error otherwise. llvm::Error Stop(); - /// Get the trace file of the given post mortem thread. - llvm::Expected GetPostMortemTraceFile(lldb::tid_t tid); - /// \return /// The stop ID of the live process being traced, or an invalid stop ID /// if the trace is in an error or invalid state. uint32_t GetStopID(); + using OnBinaryDataReadCallback = + std::function data)>; + using OnCpusBinaryDataReadCallback = std::function> + &cpu_to_data)>; + + /// Fetch binary data associated with a thread, either live or postmortem, and + /// pass it to the given callback. The reason of having a callback is to free + /// the caller from having to manage the life cycle of the data and to hide + /// the different data fetching procedures that exist for live and post mortem + /// threads. + /// + /// The fetched data is not persisted after the callback is invoked. + /// + /// \param[in] tid + /// The tid who owns the data. + /// + /// \param[in] kind + /// The kind of data to read. + /// + /// \param[in] callback + /// The callback to be invoked once the data was successfully read. Its + /// return value, which is an \a llvm::Error, is returned by this + /// function. + /// + /// \return + /// An \a llvm::Error if the data couldn't be fetched, or the return value + /// of the callback, otherwise. + llvm::Error OnThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Fetch binary data associated with a cpu, either live or postmortem, and + /// pass it to the given callback. The reason of having a callback is to free + /// the caller from having to manage the life cycle of the data and to hide + /// the different data fetching procedures that exist for live and post mortem + /// cpus. + /// + /// The fetched data is not persisted after the callback is invoked. + /// + /// \param[in] cpu_id + /// The cpu who owns the data. + /// + /// \param[in] kind + /// The kind of data to read. + /// + /// \param[in] callback + /// The callback to be invoked once the data was successfully read. Its + /// return value, which is an \a llvm::Error, is returned by this + /// function. + /// + /// \return + /// An \a llvm::Error if the data couldn't be fetched, or the return value + /// of the callback, otherwise. + llvm::Error OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id, llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Similar to \a OnCpuBinaryDataRead but this is able to fetch the same data + /// from all cpus at once. + llvm::Error OnAllCpusBinaryDataRead(llvm::StringRef kind, + OnCpusBinaryDataReadCallback callback); + + /// \return + /// All the currently traced processes. + std::vector GetAllProcesses(); + + /// \return + /// The list of cpus being traced. Might be empty depending on the + /// plugin. + llvm::ArrayRef GetTracedCpus(); + + /// Helper method for reading a data file and passing its data to the given + /// callback. + static llvm::Error OnDataFileRead(FileSpec file, + OnBinaryDataReadCallback callback); + protected: + /// Get the currently traced live process. + /// + /// \return + /// If it's not a live process, return \a nullptr. + Process *GetLiveProcess(); + + /// Get the currently traced postmortem processes. + /// + /// \return + /// If it's not a live process session, return an empty list. + llvm::ArrayRef GetPostMortemProcesses(); + + /// Dispatcher for live trace data requests with some additional error + /// checking. + llvm::Expected> + GetLiveTraceBinaryData(const TraceGetBinaryDataRequest &request, + uint64_t expected_size); + + /// Implementation of \a OnThreadBinaryDataRead() for live threads. + llvm::Error OnLiveThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Implementation of \a OnLiveBinaryDataRead() for live cpus. + llvm::Error OnLiveCpuBinaryDataRead(lldb::cpu_id_t cpu, llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Implementation of \a OnThreadBinaryDataRead() for post mortem threads. + llvm::Error + OnPostMortemThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Implementation of \a OnCpuBinaryDataRead() for post mortem cpus. + llvm::Error OnPostMortemCpuBinaryDataRead(lldb::cpu_id_t cpu_id, + llvm::StringRef kind, + OnBinaryDataReadCallback callback); + + /// Get the file path containing data of a postmortem thread given a data + /// identifier. + /// + /// \param[in] tid + /// The thread whose data is requested. + /// + /// \param[in] kind + /// The kind of data requested. + /// + /// \return + /// The file spec containing the requested data, or an \a llvm::Error in + /// case of failures. + llvm::Expected GetPostMortemThreadDataFile(lldb::tid_t tid, + llvm::StringRef kind); + + /// Get the file path containing data of a postmortem cpu given a data + /// identifier. + /// + /// \param[in] cpu_id + /// The cpu whose data is requested. + /// + /// \param[in] kind + /// The kind of data requested. + /// + /// \return + /// The file spec containing the requested data, or an \a llvm::Error in + /// case of failures. + llvm::Expected GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, + llvm::StringRef kind); + + /// Associate a given thread with a data file using a data identifier. + /// + /// \param[in] tid + /// The thread associated with the data file. + /// + /// \param[in] kind + /// The kind of data being registered. + /// + /// \param[in] file_spec + /// The path of the data file. + void SetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind, + FileSpec file_spec); + + /// Associate a given cpu with a data file using a data identifier. + /// + /// \param[in] cpu_id + /// The cpu associated with the data file. + /// + /// \param[in] kind + /// The kind of data being registered. + /// + /// \param[in] file_spec + /// The path of the data file. + void SetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, llvm::StringRef kind, + FileSpec file_spec); + /// Get binary data of a live thread given a data identifier. /// /// \param[in] tid @@ -236,9 +436,23 @@ protected: /// \return /// A vector of bytes with the requested data, or an \a llvm::Error in /// case of failures. - llvm::Expected> + llvm::Expected> GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind); + /// Get binary data of a live cpu given a data identifier. + /// + /// \param[in] cpu_id + /// The cpu whose data is requested. + /// + /// \param[in] kind + /// The kind of data requested. + /// + /// \return + /// A vector of bytes with the requested data, or an \a llvm::Error in + /// case of failures. + llvm::Expected> + GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind); + /// Get binary data of the current process given a data identifier. /// /// \param[in] kind @@ -247,17 +461,23 @@ protected: /// \return /// A vector of bytes with the requested data, or an \a llvm::Error in /// case of failures. - llvm::Expected> + llvm::Expected> GetLiveProcessBinaryData(llvm::StringRef kind); /// Get the size of the data returned by \a GetLiveThreadBinaryData - llvm::Optional GetLiveThreadBinaryDataSize(lldb::tid_t tid, - llvm::StringRef kind); + std::optional GetLiveThreadBinaryDataSize(lldb::tid_t tid, + llvm::StringRef kind); + + /// Get the size of the data returned by \a GetLiveCpuBinaryData + std::optional GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, + llvm::StringRef kind); /// Get the size of the data returned by \a GetLiveProcessBinaryData - llvm::Optional GetLiveProcessBinaryDataSize(llvm::StringRef kind); + std::optional GetLiveProcessBinaryDataSize(llvm::StringRef kind); + /// Constructor for post mortem processes - Trace() = default; + Trace(llvm::ArrayRef postmortem_processes, + std::optional> postmortem_cpus); /// Constructor for a live process Trace(Process &live_process) : m_live_process(&live_process) {} @@ -287,22 +507,92 @@ protected: /// /// \param[in] state /// The jLLDBTraceGetState response. - virtual void - DoRefreshLiveProcessState(llvm::Expected state) = 0; + /// + /// \param[in] json_response + /// The original JSON response as a string. It might be useful to redecode + /// it if it contains custom data for a specific trace plug-in. + /// + /// \return + /// \b Error::success() if this operation succeedes, or an actual error + /// otherwise. + virtual llvm::Error + DoRefreshLiveProcessState(TraceGetStateResponse state, + llvm::StringRef json_response) = 0; + + /// Return the list of processes traced by this instance. None of the returned + /// pointers are invalid. + std::vector GetTracedProcesses(); - /// Method to be invoked by the plug-in to refresh the live process state. + /// Method to be invoked by the plug-in to refresh the live process state. It + /// will invoked DoRefreshLiveProcessState at some point, which should be + /// implemented by the plug-in for custom state handling. + /// + /// The result is cached through the same process stop. Even in the case of + /// errors, it caches the error. /// - /// The result is cached through the same process stop. - void RefreshLiveProcessState(); + /// \return + /// An error message if this operation failed, or \b nullptr otherwise. + const char *RefreshLiveProcessState(); +private: uint32_t m_stop_id = LLDB_INVALID_STOP_ID; + /// Process traced by this object if doing live tracing. Otherwise it's null. Process *m_live_process = nullptr; - /// tid -> data kind -> size - std::map> - m_live_thread_data; - /// data kind -> size - std::unordered_map m_live_process_data; + + /// We package all the data that can change upon process stops to make sure + /// this contract is very visible. + /// This variable should only be accessed directly by constructores or live + /// process data refreshers. + struct Storage { + /// Portmortem processes traced by this object if doing non-live tracing. + /// Otherwise it's empty. + std::vector postmortem_processes; + + /// These data kinds are returned by lldb-server when fetching the state of + /// the tracing session. The size in bytes can be used later for fetching + /// the data in batches. + /// \{ + + /// tid -> data kind -> size + llvm::DenseMap> + live_thread_data; + + /// cpu id -> data kind -> size + llvm::DenseMap> + live_cpu_data_sizes; + /// cpu id -> data kind -> bytes + llvm::DenseMap>> + live_cpu_data; + + /// data kind -> size + llvm::DenseMap live_process_data; + /// \} + + /// The list of cpus being traced. Might be \b None depending on the + /// plug-in. + std::optional> cpus; + + /// Postmortem traces can specific additional data files, which are + /// represented in this variable using a data kind identifier for each file. + /// \{ + + /// tid -> data kind -> file + llvm::DenseMap> + postmortem_thread_data; + + /// cpu id -> data kind -> file + llvm::DenseMap> + postmortem_cpu_data; + + /// \} + + std::optional live_refresh_error; + } m_storage; + + /// Get the storage after refreshing the data in the case of a live process. + Storage &GetUpdatedStorage(); }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Target/TraceCursor.h b/gnu/llvm/lldb/include/lldb/Target/TraceCursor.h index 14fc00d5f95..cfc25b0cedc 100644 --- a/gnu/llvm/lldb/include/lldb/Target/TraceCursor.h +++ b/gnu/llvm/lldb/include/lldb/Target/TraceCursor.h @@ -12,10 +12,12 @@ #include "lldb/lldb-private.h" #include "lldb/Target/ExecutionContext.h" +#include namespace lldb_private { -/// Class used for iterating over the instructions of a thread's trace. +/// Class used for iterating over the instructions of a thread's trace, among +/// other kinds of information. /// /// This class attempts to be a generic interface for accessing the instructions /// of the trace so that each Trace plug-in can reconstruct, represent and store @@ -23,78 +25,80 @@ namespace lldb_private { /// technology. /// /// Live processes: -/// In the case of a live process trace, an instance of a \a TraceCursor should -/// point to the trace at the moment it was collected. If the process is later -/// resumed and new trace data is collected, that should leave that old cursor -/// unaffected. +/// In the case of a live process trace, an instance of a \a TraceCursor +/// should point to the trace at the moment it was collected. If the process +/// is later resumed and new trace data is collected, then it's up to each +/// trace plug-in to decide whether to leave the old cursor unaffected or not. /// -/// Errors in the trace: -/// As there could be errors when reconstructing the instructions of a trace, -/// these errors are represented as failed instructions, and the cursor can -/// point at them. The consumer should invoke \a TraceCursor::GetError() to -/// check if the cursor is pointing to either a valid instruction or an error. +/// Cursor items: +/// A \a TraceCursor can point at one of the following items: /// -/// Instructions: -/// A \a TraceCursor always points to a specific instruction or error in the -/// trace. +/// Errors: +/// As there could be errors when reconstructing the instructions of a +/// trace, these errors are represented as failed instructions, and the +/// cursor can point at them. +/// +/// Events: +/// The cursor can also point at events in the trace, which aren't errors +/// nor instructions. An example of an event could be a context switch in +/// between two instructions. +/// +/// Instruction: +/// An actual instruction with a memory address. /// /// Defaults: -/// By default, the cursor points at the end item of the trace, moves -/// backwards, has a move granularity of \a -/// eTraceInstructionControlFlowTypeInstruction (i.e. visit every instruction) -/// and stops at every error (the "ignore errors" flag is \b false). See the -/// \a TraceCursor::Next() method for more documentation. +/// By default, the cursor points at the most recent item in the trace and is +/// set up to iterate backwards. See the \a TraceCursor::Next() method for +/// more documentation. /// /// Sample usage: /// -/// TraceCursorUP cursor = trace.GetTrace(thread); -/// -/// cursor->SetGranularity(eTraceInstructionControlFlowTypeCall | -/// eTraceInstructionControlFlowTypeReturn); -/// -/// do { -/// if (llvm::Error error = cursor->GetError()) -/// cout << "error found at: " << llvm::toString(error) << endl; -/// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeCall) -/// std::cout << "call found at " << cursor->GetLoadAddress() << -/// std::endl; -/// else if (cursor->GetInstructionControlFlowType() & -/// eTraceInstructionControlFlowTypeReturn) -/// std::cout << "return found at " << cursor->GetLoadAddress() << -/// std::endl; -/// } while(cursor->Next()); -/// -/// Low level traversal: -/// Unlike the \a TraceCursor::Next() API, which uses a given granularity and -/// direction to advance the cursor, the \a TraceCursor::Seek() method can be -/// used to reposition the cursor to an offset of the end, beginning, or -/// current position of the trace. +/// TraceCursorSP cursor = trace.GetTrace(thread); +/// +/// for (; cursor->HasValue(); cursor->Next()) { +/// TraceItemKind kind = cursor->GetItemKind(); +/// switch (cursor->GetItemKind()): +/// case eTraceItemKindError: +/// cout << "error found: " << cursor->GetError() << endl; +/// break; +/// case eTraceItemKindEvent: +/// cout << "event found: " << cursor->GetEventTypeAsString() << endl; +/// break; +/// case eTraceItemKindInstruction: +/// std::cout << "instructions found at " << cursor->GetLoadAddress() << +/// std::endl; break; +/// } +/// } +/// +/// As the trace might be empty or the cursor might have reached the end of the +/// trace, you should always invoke \a HasValue() to make sure you don't access +/// invalid memory. +/// +/// Random accesses: +/// +/// The Trace Cursor offer random acesses in the trace via two APIs: +/// +/// TraceCursor::Seek(): +/// Unlike the \a TraceCursor::Next() API, which moves instruction by +/// instruction, the \a TraceCursor::Seek() method can be used to +/// reposition the cursor to an offset of the end, beginning, or current +/// position of the trace. +/// +/// TraceCursor::GetId() / TraceCursor::SetId(id): +/// Each item (error or instruction) in the trace has a numeric identifier +/// which is defined by the trace plug-in. It's possible to access the id +/// of the current item using GetId(), and to reposition the cursor to a +/// given id using SetId(id). +/// +/// You can read more in the documentation of these methods. class TraceCursor { public: - /// Helper enum to indicate the reference point when invoking - /// \a TraceCursor::Seek(). - enum class SeekType { - /// The beginning of the trace, i.e the oldest item. - Set = 0, - /// The current position in the trace. - Current, - /// The end of the trace, i.e the most recent item. - End - }; - /// Create a cursor that initially points to the end of the trace, i.e. the /// most recent item. TraceCursor(lldb::ThreadSP thread_sp); virtual ~TraceCursor() = default; - /// Set the granularity to use in the \a TraceCursor::Next() method. - void SetGranularity(lldb::TraceInstructionControlFlowType granularity); - - /// Set the "ignore errors" flag to use in the \a TraceCursor::Next() method. - void SetIgnoreErrors(bool ignore_errors); - /// Set the direction to use in the \a TraceCursor::Next() method. /// /// \param[in] forwards @@ -108,8 +112,7 @@ public: /// \b true if the current direction is forwards, \b false if backwards. bool IsForwards() const; - /// Move the cursor to the next instruction that matches the current - /// granularity. + /// Move the cursor to the next item (instruction or error). /// /// Direction: /// The traversal is done following the current direction of the trace. If @@ -117,95 +120,174 @@ public: /// chronologically. Otherwise, the traversal is done in /// the opposite direction. By default, a cursor moves backwards unless /// changed with \a TraceCursor::SetForwards(). + virtual void Next() = 0; + + /// \return + /// \b true if the cursor is pointing to a valid item. \b false if the + /// cursor has reached the end of the trace. + virtual bool HasValue() const = 0; + + /// Instruction identifiers: /// - /// Granularity: - /// The cursor will traverse the trace looking for the first instruction - /// that matches the current granularity. If there aren't any matching - /// instructions, the cursor won't move, to give the opportunity of - /// changing granularities. + /// When building complex higher level tools, fast random accesses in the + /// trace might be needed, for which each instruction requires a unique + /// identifier within its thread trace. For example, a tool might want to + /// repeatedly inspect random consecutive portions of a trace. This means that + /// it will need to first move quickly to the beginning of each section and + /// then start its iteration. Given that the number of instructions can be in + /// the order of hundreds of millions, fast random access is necessary. /// - /// Ignore errors: - /// If the "ignore errors" flags is \b false, the traversal will stop as - /// soon as it finds an error in the trace and the cursor will point at - /// it. + /// An example of such a tool could be an inspector of the call graph of a + /// trace, where each call is represented with its start and end instructions. + /// Inspecting all the instructions of a call requires moving to its first + /// instruction and then iterating until the last instruction, which following + /// the pattern explained above. + /// + /// Instead of using 0-based indices as identifiers, each Trace plug-in can + /// decide the nature of these identifiers and thus no assumptions can be made + /// regarding their ordering and sequentiality. The reason is that an + /// instruction might be encoded by the plug-in in a way that hides its actual + /// 0-based index in the trace, but it's still possible to efficiently find + /// it. + /// + /// Requirements: + /// - For a given thread, no two instructions have the same id. + /// - In terms of efficiency, moving the cursor to a given id should be as + /// fast as possible, but not necessarily O(1). That's why the recommended + /// way to traverse sequential instructions is to use the \a + /// TraceCursor::Next() method and only use \a TraceCursor::GoToId(id) + /// sparingly. + + /// Make the cursor point to the item whose identifier is \p id. /// /// \return - /// \b true if the cursor effectively moved, \b false otherwise. - virtual bool Next() = 0; + /// \b true if the given identifier exists and the cursor effectively + /// moved to it. Otherwise, \b false is returned and the cursor now points + /// to an invalid item, i.e. calling \a HasValue() will return \b false. + virtual bool GoToId(lldb::user_id_t id) = 0; + + /// \return + /// \b true if and only if there's an instruction item with the given \p + /// id. + virtual bool HasId(lldb::user_id_t id) const = 0; + + /// \return + /// A unique identifier for the instruction or error this cursor is + /// pointing to. + virtual lldb::user_id_t GetId() const = 0; + /// \} /// Make the cursor point to an item in the trace based on an origin point and - /// an offset. This API doesn't distinguishes instruction types nor errors in - /// the trace, unlike the \a TraceCursor::Next() method. + /// an offset. /// /// The resulting position of the trace is /// origin + offset /// - /// If this resulting position would be out of bounds, it will be adjusted to - /// the last or first item in the trace correspondingly. + /// If this resulting position would be out of bounds, the trace then points + /// to an invalid item, i.e. calling \a HasValue() returns \b false. /// /// \param[in] offset /// How many items to move forwards (if positive) or backwards (if - /// negative) from the given origin point. + /// negative) from the given origin point. For example, if origin is \b + /// End, then a negative offset would move backward in the trace, but a + /// positive offset would move past the trace to an invalid item. /// /// \param[in] origin /// The reference point to use when moving the cursor. /// /// \return - /// The number of trace items moved from the origin. - virtual size_t Seek(ssize_t offset, SeekType origin) = 0; + /// \b true if and only if the cursor ends up pointing to a valid item. + virtual bool Seek(int64_t offset, lldb::TraceCursorSeekType origin) = 0; /// \return /// The \a ExecutionContextRef of the backing thread from the creation time /// of this cursor. ExecutionContextRef &GetExecutionContextRef(); - /// Instruction or error information + /// Trace item information (instructions, errors and events) /// \{ + /// \return + /// The kind of item the cursor is pointing at. + virtual lldb::TraceItemKind GetItemKind() const = 0; + /// \return /// Whether the cursor points to an error or not. - virtual bool IsError() = 0; + bool IsError() const; + + /// \return + /// The error message the cursor is pointing at. + virtual const char *GetError() const = 0; + + /// \return + /// Whether the cursor points to an event or not. + bool IsEvent() const; + + /// \return + /// The specific kind of event the cursor is pointing at. + virtual lldb::TraceEvent GetEventType() const = 0; + + /// \return + /// A human-readable description of the event this cursor is pointing at. + const char *GetEventTypeAsString() const; + + /// \return + /// A human-readable description of the given event. + static const char *EventKindToString(lldb::TraceEvent event_kind); + + /// \return + /// Whether the cursor points to an instruction. + bool IsInstruction() const; - /// Get the corresponding error message if the cursor points to an error in - /// the trace. + /// \return + /// The load address of the instruction the cursor is pointing at. + virtual lldb::addr_t GetLoadAddress() const = 0; + + /// Get the CPU associated with the current trace item. + /// + /// This call might not be O(1), so it's suggested to invoke this method + /// whenever an eTraceEventCPUChanged event is fired. /// /// \return - /// \b llvm::Error::success if the cursor is not pointing to an error in - /// the trace. Otherwise return an \a llvm::Error describing the issue. - virtual llvm::Error GetError() = 0; + /// The requested CPU id, or LLDB_INVALID_CPU_ID if this information is + /// not available for the current item. + virtual lldb::cpu_id_t GetCPU() const = 0; + /// Get the last hardware clock value that was emitted before the current + /// trace item. + /// + /// This call might not be O(1), so it's suggested to invoke this method + /// whenever an eTraceEventHWClockTick event is fired. + /// /// \return - /// The load address of the instruction the cursor is pointing at. If the - /// cursor points to an error in the trace, return \b - /// LLDB_INVALID_ADDRESS. - virtual lldb::addr_t GetLoadAddress() = 0; + /// The requested HW clock value, or \a std::nullopt if this information + /// is not available for the current item. + virtual std::optional GetHWClock() const = 0; - /// Get the timestamp counter associated with the current instruction. - /// Modern Intel, ARM and AMD processors support this counter. However, a - /// trace plugin might decide to use a different time unit instead of an - /// actual TSC. + /// Get the approximate wall clock time in nanoseconds at which the current + /// trace item was executed. Each trace plug-in has a different definition for + /// what time 0 means. /// /// \return - /// The timestamp or \b llvm::None if not available. - virtual llvm::Optional GetTimestampCounter() = 0; + /// The approximate wall clock time for the trace item, or \a std::nullopt + /// if not available. + virtual std::optional GetWallClockTime() const = 0; + /// Get some metadata associated with a synchronization point event. As + /// different trace technologies might have different values for this, + /// we return a string for flexibility. + /// /// \return - /// The \a lldb::TraceInstructionControlFlowType categories the - /// instruction the cursor is pointing at falls into. If the cursor points - /// to an error in the trace, return \b 0. - virtual lldb::TraceInstructionControlFlowType - GetInstructionControlFlowType() = 0; + /// A string representing some metadata associated with a + /// \a eTraceEventSyncPoint event. \b std::nullopt if no metadata is + /// available. + virtual std::optional GetSyncPointMetadata() const = 0; /// \} protected: ExecutionContextRef m_exe_ctx_ref; - - lldb::TraceInstructionControlFlowType m_granularity = - lldb::eTraceInstructionControlFlowTypeInstruction; - bool m_ignore_errors = false; bool m_forwards = false; }; - } // namespace lldb_private #endif // LLDB_TARGET_TRACE_CURSOR_H diff --git a/gnu/llvm/lldb/include/lldb/Target/TraceDumper.h b/gnu/llvm/lldb/include/lldb/Target/TraceDumper.h new file mode 100644 index 00000000000..ca3bf2c0880 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Target/TraceDumper.h @@ -0,0 +1,433 @@ +//===-- TraceDumper.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/TraceCursor.h" +#include + +#ifndef LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H +#define LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H + +namespace lldb_private { + +/// Class that holds the configuration used by \a TraceDumper for +/// traversing and dumping instructions. +struct TraceDumperOptions { + /// If \b true, the cursor will be iterated forwards starting from the + /// oldest instruction. Otherwise, the iteration starts from the most + /// recent instruction. + bool forwards = false; + /// Dump only instruction addresses without disassembly nor symbol + /// information. + bool raw = false; + /// Dump in json format. + bool json = false; + /// When dumping in JSON format, pretty print the output. + bool pretty_print_json = false; + /// For each trace item, print the corresponding timestamp in nanoseconds if + /// available. + bool show_timestamps = false; + /// Dump the events that happened between instructions. + bool show_events = false; + /// Dump events and none of the instructions. + bool only_events = false; + /// For each instruction, print the instruction kind. + bool show_control_flow_kind = false; + /// Optional custom id to start traversing from. + std::optional id; + /// Optional number of instructions to skip from the starting position + /// of the cursor. + std::optional skip; +}; + +/// Class used to dump the instructions of a \a TraceCursor using its current +/// state and granularity. +class TraceDumper { +public: + /// Helper struct that holds symbol, disassembly and address information of an + /// instruction. + struct SymbolInfo { + SymbolContext sc; + Address address; + lldb::DisassemblerSP disassembler; + lldb::InstructionSP instruction; + lldb_private::ExecutionContext exe_ctx; + }; + + /// Helper struct that holds all the information we know about a trace item + struct TraceItem { + lldb::user_id_t id; + lldb::addr_t load_address; + std::optional timestamp; + std::optional hw_clock; + std::optional sync_point_metadata; + std::optional error; + std::optional event; + std::optional symbol_info; + std::optional prev_symbol_info; + std::optional cpu_id; + }; + + /// An object representing a traced function call. + /// + /// A function call is represented using segments and subcalls. + /// + /// TracedSegment: + /// A traced segment is a maximal list of consecutive traced instructions + /// that belong to the same function call. A traced segment will end in + /// three possible ways: + /// - With a call to a function deeper in the callstack. In this case, + /// most of the times this nested call will return + /// and resume with the next segment of this segment's owning function + /// call. More on this later. + /// - Abruptly due to end of trace. In this case, we weren't able to trace + /// the end of this function call. + /// - Simply a return higher in the callstack. + /// + /// In terms of implementation details, as segment can be represented with + /// the beginning and ending instruction IDs from the instruction trace. + /// + /// UntracedPrefixSegment: + /// It might happen that we didn't trace the beginning of a function and we + /// saw it for the first time as part of a return. As a way to signal these + /// cases, we have a placeholder UntracedPrefixSegment class that completes the + /// callgraph. + /// + /// Example: + /// We might have this piece of execution: + /// + /// main() [offset 0x00 to 0x20] [traced instruction ids 1 to 4] + /// foo() [offset 0x00 to 0x80] [traced instruction ids 5 to 20] # main + /// invoked foo + /// main() [offset 0x24 to 0x40] [traced instruction ids 21 to 30] + /// + /// In this case, our function main invokes foo. We have 3 segments: main + /// [offset 0x00 to 0x20], foo() [offset 0x00 to 0x80], and main() [offset + /// 0x24 to 0x40]. We also have the instruction ids from the corresponding + /// linear instruction trace for each segment. + /// + /// But what if we started tracing since the middle of foo? Then we'd have + /// an incomplete trace + /// + /// foo() [offset 0x30 to 0x80] [traced instruction ids 1 to 10] + /// main() [offset 0x24 to 0x40] [traced instruction ids 11 to 20] + /// + /// Notice that we changed the instruction ids because this is a new trace. + /// Here, in order to have a somewhat complete tree with good traversal + /// capabilities, we can create an UntracedPrefixSegment to signal the portion of + /// main() that we didn't trace. We don't know if this segment was in fact + /// multiple segments with many function calls. We'll never know. The + /// resulting tree looks like the following: + /// + /// main() [untraced] + /// foo() [offset 0x30 to 0x80] [traced instruction ids 1 to 10] + /// main() [offset 0x24 to 0x40] [traced instruction ids 11 to 20] + /// + /// And in pseudo-code: + /// + /// FunctionCall [ + /// UntracedPrefixSegment { + /// symbol: main() + /// nestedCall: FunctionCall [ # this untraced segment has a nested + /// call + /// TracedSegment { + /// symbol: foo() + /// fromInstructionId: 1 + /// toInstructionId: 10 + /// nestedCall: none # this doesn't have a nested call + /// } + /// } + /// ], + /// TracedSegment { + /// symbol: main() + /// fromInstructionId: 11 + /// toInstructionId: 20 + /// nestedCall: none # this also doesn't have a nested call + /// } + /// ] + /// + /// We can see the nested structure and how instructions are represented as + /// segments. + /// + /// + /// Returns: + /// Code doesn't always behave intuitively. Some interesting functions + /// might modify the stack and thus change the behavior of common + /// instructions like CALL and RET. We try to identify these cases, and + /// the result is that the return edge from a segment might connect with a + /// function call very high the stack. For example, you might have + /// + /// main() + /// foo() + /// bar() + /// # here bar modifies the stack and pops foo() from it. Then it + /// finished the a RET (return) + /// main() # we came back directly to main() + /// + /// I have observed some trampolines doing this, as well as some std + /// functions (like ostream functions). So consumers should be aware of + /// this. + /// + /// There are all sorts of "abnormal" behaviors you can see in code, and + /// whenever we fail at identifying what's going on, we prefer to create a + /// new tree. + /// + /// Function call forest: + /// A single tree would suffice if a trace didn't contain errors nor + /// abnormal behaviors that made our algorithms fail. Sadly these + /// anomalies exist and we prefer not to use too many heuristics and + /// probably end up lying to the user. So we create a new tree from the + /// point we can't continue using the previous tree. This results in + /// having a forest instead of a single tree. This is probably the best we + /// can do if we consumers want to use this data to perform performance + /// analysis or reverse debugging. + /// + /// Non-functions: + /// Not everything in a program is a function. There are blocks of + /// instructions that are simply labeled or even regions without symbol + /// information that we don't what they are. We treat all of them as + /// functions for simplicity. + /// + /// Errors: + /// Whenever an error is found, a new tree with a single segment is + /// created. All consecutive errors after the original one are then + /// appended to this segment. As a note, something that GDB does is to use + /// some heuristics to merge trees that were interrupted by errors. We are + /// leaving that out of scope until a feature like that one is really + /// needed. + + /// Forward declaration + class FunctionCall; + using FunctionCallUP = std::unique_ptr; + + class FunctionCall { + public: + class TracedSegment { + public: + /// \param[in] cursor_sp + /// A cursor pointing to the beginning of the segment. + /// + /// \param[in] symbol_info + /// The symbol information of the first instruction of the segment. + /// + /// \param[in] call + /// The FunctionCall object that owns this segment. + TracedSegment(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info, FunctionCall &owning_call) + : m_first_insn_id(cursor_sp->GetId()), + m_last_insn_id(cursor_sp->GetId()), + m_first_symbol_info(symbol_info), m_last_symbol_info(symbol_info), + m_owning_call(owning_call) {} + + /// \return + /// The chronologically first instruction ID in this segment. + lldb::user_id_t GetFirstInstructionID() const; + /// \return + /// The chronologically last instruction ID in this segment. + lldb::user_id_t GetLastInstructionID() const; + + /// \return + /// The symbol information of the chronologically first instruction ID + /// in this segment. + const SymbolInfo &GetFirstInstructionSymbolInfo() const; + + /// \return + /// The symbol information of the chronologically last instruction ID in + /// this segment. + const SymbolInfo &GetLastInstructionSymbolInfo() const; + + /// \return + /// Get the call that owns this segment. + const FunctionCall &GetOwningCall() const; + + /// Append a new instruction to this segment. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the new instruction. + /// + /// \param[in] symbol_info + /// The symbol information of the new instruction. + void AppendInsn(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Create a nested call at the end of this segment. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of the nested call. + /// + /// \param[in] symbol_info + /// The symbol information of the first instruction of the nested call. + FunctionCall &CreateNestedCall(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Executed the given callback if there's a nested call at the end of + /// this segment. + void IfNestedCall(std::function + callback) const; + + private: + TracedSegment(const TracedSegment &) = delete; + TracedSegment &operator=(TracedSegment const &); + + /// Delimiting instruction IDs taken chronologically. + /// \{ + lldb::user_id_t m_first_insn_id; + lldb::user_id_t m_last_insn_id; + /// \} + /// An optional nested call starting at the end of this segment. + FunctionCallUP m_nested_call; + /// The symbol information of the delimiting instructions + /// \{ + SymbolInfo m_first_symbol_info; + SymbolInfo m_last_symbol_info; + /// \} + FunctionCall &m_owning_call; + }; + + class UntracedPrefixSegment { + public: + /// Note: Untraced segments can only exist if have also seen a traced + /// segment of the same function call. Thus, we can use those traced + /// segments if we want symbol information and such. + + UntracedPrefixSegment(FunctionCallUP &&nested_call) + : m_nested_call(std::move(nested_call)) {} + + const FunctionCall &GetNestedCall() const; + + private: + UntracedPrefixSegment(const UntracedPrefixSegment &) = delete; + UntracedPrefixSegment &operator=(UntracedPrefixSegment const &); + FunctionCallUP m_nested_call; + }; + + /// Create a new function call given an instruction. This will also create a + /// segment for that instruction. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of that function call. + /// + /// \param[in] symbol_info + /// The symbol information of that first instruction. + FunctionCall(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// Append a new traced segment to this funciton call. + /// + /// \param[in] cursor_sp + /// A cursor pointing to the first instruction of the new segment. + /// + /// \param[in] symbol_info + /// The symbol information of that first instruction. + void AppendSegment(const lldb::TraceCursorSP &cursor_sp, + const SymbolInfo &symbol_info); + + /// \return + /// The symbol info of some traced instruction of this call. + const SymbolInfo &GetSymbolInfo() const; + + /// \return + /// \b true if and only if the instructions in this function call are + /// trace errors, in which case this function call is a fake one. + bool IsError() const; + + /// \return + /// The list of traced segments of this call. + const std::deque &GetTracedSegments() const; + + /// \return + /// A non-const reference to the most-recent traced segment. + TracedSegment &GetLastTracedSegment(); + + /// Create an untraced segment for this call that jumps to the provided + /// nested call. + void SetUntracedPrefixSegment(FunctionCallUP &&nested_call); + + /// \return + /// A optional to the untraced prefix segment of this call. + const std::optional & + GetUntracedPrefixSegment() const; + + /// \return + /// A pointer to the parent call. It may be \b nullptr. + FunctionCall *GetParentCall() const; + + void SetParentCall(FunctionCall &parent_call); + + private: + /// An optional untraced segment that precedes all the traced segments. + std::optional m_untraced_prefix_segment; + /// The traced segments in order. We used a deque to prevent moving these + /// objects when appending to the list, which would happen with vector. + std::deque m_traced_segments; + /// The parent call, which might be null. Useful for reconstructing + /// callstacks. + FunctionCall *m_parent_call = nullptr; + /// Whether this call represents a list of consecutive errors. + bool m_is_error; + }; + + /// Interface used to abstract away the format in which the instruction + /// information will be dumped. + class OutputWriter { + public: + virtual ~OutputWriter() = default; + + /// Notify this writer that the cursor ran out of data. + virtual void NoMoreData() {} + + /// Dump a trace item (instruction, error or event). + virtual void TraceItem(const TraceItem &item) = 0; + + /// Dump a function call forest. + virtual void + FunctionCallForest(const std::vector &forest) = 0; + }; + + /// Create a instruction dumper for the cursor. + /// + /// \param[in] cursor + /// The cursor whose instructions will be dumped. + /// + /// \param[in] s + /// The stream where to dump the instructions to. + /// + /// \param[in] options + /// Additional options for configuring the dumping. + TraceDumper(lldb::TraceCursorSP cursor_sp, Stream &s, + const TraceDumperOptions &options); + + /// Dump \a count instructions of the thread trace starting at the current + /// cursor position. + /// + /// This effectively moves the cursor to the next unvisited position, so that + /// a subsequent call to this method continues where it left off. + /// + /// \param[in] count + /// The number of instructions to print. + /// + /// \return + /// The instruction id of the last traversed instruction, or \b + /// std::nullopt if no instructions were visited. + std::optional DumpInstructions(size_t count); + + /// Dump all function calls forwards chronologically and hierarchically + void DumpFunctionCalls(); + +private: + /// Create a trace item for the current position without symbol information. + TraceItem CreatRawTraceItem(); + + lldb::TraceCursorSP m_cursor_sp; + TraceDumperOptions m_options; + std::unique_ptr m_writer_up; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_TRACE_INSTRUCTION_DUMPER_H diff --git a/gnu/llvm/lldb/include/lldb/Target/TraceExporter.h b/gnu/llvm/lldb/include/lldb/Target/TraceExporter.h index 6560b39fd42..d5a06c499a6 100644 --- a/gnu/llvm/lldb/include/lldb/Target/TraceExporter.h +++ b/gnu/llvm/lldb/include/lldb/Target/TraceExporter.h @@ -10,6 +10,8 @@ #define LLDB_TARGET_TRACE_EXPORTER_H #include "lldb/Core/PluginInterface.h" +#include "lldb/lldb-forward.h" +#include "llvm/Support/Error.h" namespace lldb_private { diff --git a/gnu/llvm/lldb/include/lldb/Target/UnixSignals.h b/gnu/llvm/lldb/include/lldb/Target/UnixSignals.h index 6fecdda12de..ff9f1ac9be1 100644 --- a/gnu/llvm/lldb/include/lldb/Target/UnixSignals.h +++ b/gnu/llvm/lldb/include/lldb/Target/UnixSignals.h @@ -10,12 +10,13 @@ #define LLDB_TARGET_UNIXSIGNALS_H #include +#include #include #include #include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" -#include "llvm/ADT/Optional.h" +#include "llvm/Support/JSON.h" namespace lldb_private { @@ -54,6 +55,9 @@ public: bool SetShouldNotify(int32_t signo, bool value); bool SetShouldNotify(const char *signal_name, bool value); + + bool ResetSignal(int32_t signo, bool reset_stop = true, + bool reset_notify = true, bool reset_suppress = true); // These provide an iterator through the signals available on this system. // Call GetFirstSignalNumber to get the first entry, then iterate on @@ -80,17 +84,29 @@ public: void RemoveSignal(int signo); + /// Track how many times signals are hit as stop reasons. + void IncrementSignalHitCount(int signo); + + /// Get the hit count statistics for signals. + /// + /// Gettings statistics on the hit counts of signals can help explain why some + /// debug sessions are slow since each stop takes a few hundred ms and some + /// software use signals a lot and can cause slow debugging performance if + /// they are used too often. Even if a signal is not stopped at, it will auto + /// continue the process and a delay will happen. + llvm::json::Value GetHitCountStatistics() const; + // Returns a current version of the data stored in this class. Version gets // incremented each time Set... method is called. uint64_t GetVersion() const; // Returns a vector of signals that meet criteria provided in arguments. Each - // should_[suppress|stop|notify] flag can be None - no filtering by this - // flag true - only signals that have it set to true are returned false - + // should_[suppress|stop|notify] flag can be std::nullopt - no filtering by + // this flag true - only signals that have it set to true are returned false - // only signals that have it set to true are returned - std::vector GetFilteredSignals(llvm::Optional should_suppress, - llvm::Optional should_stop, - llvm::Optional should_notify); + std::vector GetFilteredSignals(std::optional should_suppress, + std::optional should_stop, + std::optional should_notify); protected: // Classes that inherit from UnixSignals can see and modify these @@ -99,12 +115,15 @@ protected: ConstString m_name; ConstString m_alias; std::string m_description; + uint32_t m_hit_count = 0; bool m_suppress : 1, m_stop : 1, m_notify : 1; + bool m_default_suppress : 1, m_default_stop : 1, m_default_notify : 1; Signal(const char *name, bool default_suppress, bool default_stop, bool default_notify, const char *description, const char *alias); ~Signal() = default; + void Reset(bool reset_stop, bool reset_notify, bool reset_suppress); }; virtual void Reset(); diff --git a/gnu/llvm/lldb/include/lldb/Target/Unwind.h b/gnu/llvm/lldb/include/lldb/Target/Unwind.h index 3faef139b00..105383ddae8 100644 --- a/gnu/llvm/lldb/include/lldb/Target/Unwind.h +++ b/gnu/llvm/lldb/include/lldb/Target/Unwind.h @@ -18,7 +18,7 @@ namespace lldb_private { class Unwind { protected: // Classes that inherit from Unwind can see and modify these - Unwind(Thread &thread) : m_thread(thread), m_unwind_mutex() {} + Unwind(Thread &thread) : m_thread(thread) {} public: virtual ~Unwind() = default; diff --git a/gnu/llvm/lldb/include/lldb/Target/UnwindLLDB.h b/gnu/llvm/lldb/include/lldb/Target/UnwindLLDB.h index f6750171c54..f80212cde3c 100644 --- a/gnu/llvm/lldb/include/lldb/Target/UnwindLLDB.h +++ b/gnu/llvm/lldb/include/lldb/Target/UnwindLLDB.h @@ -119,7 +119,7 @@ private: RegisterContextLLDBSP reg_ctx_lldb_sp; // These are all RegisterContextUnwind's - Cursor() : sctx(), reg_ctx_lldb_sp() {} + Cursor() = default; private: Cursor(const Cursor &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Utility/AnsiTerminal.h b/gnu/llvm/lldb/include/lldb/Utility/AnsiTerminal.h index c391adb2cf8..67795971d2c 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/AnsiTerminal.h +++ b/gnu/llvm/lldb/include/lldb/Utility/AnsiTerminal.h @@ -1,7 +1,3 @@ -#ifndef LLDB_UTILITY_ANSITERMINAL_H - -#define LLDB_UTILITY_ANSITERMINAL_H - //===---------------------AnsiTerminal.h ------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -10,6 +6,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLDB_UTILITY_ANSITERMINAL_H +#define LLDB_UTILITY_ANSITERMINAL_H + #define ANSI_FG_COLOR_BLACK 30 #define ANSI_FG_COLOR_RED 31 #define ANSI_FG_COLOR_GREEN 32 @@ -19,6 +18,15 @@ #define ANSI_FG_COLOR_CYAN 36 #define ANSI_FG_COLOR_WHITE 37 +#define ANSI_FG_COLOR_BRIGHT_BLACK 90 +#define ANSI_FG_COLOR_BRIGHT_RED 91 +#define ANSI_FG_COLOR_BRIGHT_GREEN 92 +#define ANSI_FG_COLOR_BRIGHT_YELLOW 93 +#define ANSI_FG_COLOR_BRIGHT_BLUE 94 +#define ANSI_FG_COLOR_BRIGHT_PURPLE 95 +#define ANSI_FG_COLOR_BRIGHT_CYAN 96 +#define ANSI_FG_COLOR_BRIGHT_WHITE 97 + #define ANSI_BG_COLOR_BLACK 40 #define ANSI_BG_COLOR_RED 41 #define ANSI_BG_COLOR_GREEN 42 @@ -28,6 +36,15 @@ #define ANSI_BG_COLOR_CYAN 46 #define ANSI_BG_COLOR_WHITE 47 +#define ANSI_BG_COLOR_BRIGHT_BLACK 100 +#define ANSI_BG_COLOR_BRIGHT_RED 101 +#define ANSI_BG_COLOR_BRIGHT_GREEN 102 +#define ANSI_BG_COLOR_BRIGHT_YELLOW 103 +#define ANSI_BG_COLOR_BRIGHT_BLUE 104 +#define ANSI_BG_COLOR_BRIGHT_PURPLE 105 +#define ANSI_BG_COLOR_BRIGHT_CYAN 106 +#define ANSI_BG_COLOR_BRIGHT_WHITE 107 + #define ANSI_SPECIAL_FRAMED 51 #define ANSI_SPECIAL_ENCIRCLED 52 @@ -67,46 +84,60 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, bool do_color = true) { // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is // false. + // clang-format off static const struct { const char *name; const char *value; } g_color_tokens[] = { #define _TO_STR2(_val) #_val #define _TO_STR(_val) _TO_STR2(_val) - {"fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END}, - {"fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END}, - {"fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END}, - {"fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END}, - {"fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END}, - {"fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END}, - {"fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END}, - {"fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END}, - {"bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END}, - {"bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END}, - {"bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END}, - {"bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END}, - {"bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END}, - {"bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END}, - {"bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END}, - {"bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END}, - {"normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END}, - {"bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END}, - {"faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END}, - {"italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END}, - {"underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END}, - {"slow-blink}", - ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END}, - {"fast-blink}", - ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END}, - {"negative}", - ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END}, - {"conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END}, - {"crossed-out}", - ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END}, + {"fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END}, + {"fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END}, + {"fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END}, + {"fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END}, + {"fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END}, + {"fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END}, + {"fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END}, + {"fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END}, + {"fg.bright.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_BLACK) ANSI_ESC_END}, + {"fg.bright.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_RED) ANSI_ESC_END}, + {"fg.bright.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_GREEN) ANSI_ESC_END}, + {"fg.bright.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_YELLOW) ANSI_ESC_END}, + {"fg.bright.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_BLUE) ANSI_ESC_END}, + {"fg.bright.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_PURPLE) ANSI_ESC_END}, + {"fg.bright.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_CYAN) ANSI_ESC_END}, + {"fg.bright.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BRIGHT_WHITE) ANSI_ESC_END}, + {"bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END}, + {"bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END}, + {"bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END}, + {"bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END}, + {"bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END}, + {"bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END}, + {"bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END}, + {"bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END}, + {"bg.bright.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_BLACK) ANSI_ESC_END}, + {"bg.bright.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_RED) ANSI_ESC_END}, + {"bg.bright.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_GREEN) ANSI_ESC_END}, + {"bg.bright.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_YELLOW) ANSI_ESC_END}, + {"bg.bright.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_BLUE) ANSI_ESC_END}, + {"bg.bright.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_PURPLE) ANSI_ESC_END}, + {"bg.bright.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_CYAN) ANSI_ESC_END}, + {"bg.bright.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BRIGHT_WHITE) ANSI_ESC_END}, + {"normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END}, + {"bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END}, + {"faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END}, + {"italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END}, + {"underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END}, + {"slow-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END}, + {"fast-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END}, + {"negative}", ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END}, + {"conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END}, + {"crossed-out}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END}, #undef _TO_STR #undef _TO_STR2 }; - auto codes = llvm::makeArrayRef(g_color_tokens); + // clang-format on + auto codes = llvm::ArrayRef(g_color_tokens); static const char tok_hdr[] = "${ansi."; diff --git a/gnu/llvm/lldb/include/lldb/Utility/Args.h b/gnu/llvm/lldb/include/lldb/Utility/Args.h index cecf6b1502b..40b9358484b 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/Args.h +++ b/gnu/llvm/lldb/include/lldb/Utility/Args.h @@ -35,11 +35,9 @@ public: struct ArgEntry { private: friend class Args; - friend struct llvm::yaml::MappingTraits; - friend struct llvm::yaml::MappingTraits; std::unique_ptr ptr; - char quote; + char quote = '\0'; char *data() { return ptr.get(); } @@ -169,7 +167,7 @@ public: /// have a nullptr const char * at the end, as the size of the list is /// embedded in the ArrayRef object. llvm::ArrayRef GetArgumentArrayRef() const { - return llvm::makeArrayRef(m_argv).drop_back(); + return llvm::ArrayRef(m_argv).drop_back(); } /// Appends a new argument to the end of the list argument list. @@ -287,8 +285,6 @@ public: char quote_char); private: - friend struct llvm::yaml::MappingTraits; - std::vector m_entries; /// The arguments as C strings with a trailing nullptr element. /// @@ -383,28 +379,4 @@ private: } // namespace lldb_private -namespace llvm { -namespace yaml { -template <> struct MappingTraits { - class NormalizedArgEntry { - public: - NormalizedArgEntry(IO &) {} - NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry) - : value(entry.ref()), quote(entry.quote) {} - lldb_private::Args::ArgEntry denormalize(IO &) { - return lldb_private::Args::ArgEntry(value, quote); - } - StringRef value; - uint8_t quote; - }; - static void mapping(IO &io, lldb_private::Args::ArgEntry &v); -}; -template <> struct MappingTraits { - static void mapping(IO &io, lldb_private::Args &v); -}; -} // namespace yaml -} // namespace llvm - -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry) - #endif // LLDB_UTILITY_ARGS_H diff --git a/gnu/llvm/lldb/include/lldb/Utility/ConstString.h b/gnu/llvm/lldb/include/lldb/Utility/ConstString.h index 52d3556418f..fe23303e14d 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/ConstString.h +++ b/gnu/llvm/lldb/include/lldb/Utility/ConstString.h @@ -12,7 +12,6 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/YAMLTraits.h" #include @@ -394,22 +393,20 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const { return sizeof(ConstString); } - /// Get the size in bytes of the current global string pool. - /// - /// Reports the size in bytes of all shared C string values, containers and - /// any other values as a byte size for the entire string pool. - /// - /// \return - /// The number of bytes that the global string pool occupies - /// in memory. - static size_t StaticMemorySize(); + struct MemoryStats { + size_t GetBytesTotal() const { return bytes_total; } + size_t GetBytesUsed() const { return bytes_used; } + size_t GetBytesUnused() const { return bytes_total - bytes_used; } + size_t bytes_total = 0; + size_t bytes_used = 0; + }; + + static MemoryStats GetMemoryStats(); protected: - template friend struct ::llvm::DenseMapInfo; + template friend struct ::llvm::DenseMapInfo; /// Only used by DenseMapInfo. static ConstString FromStringPoolPointer(const char *ptr) { ConstString s; @@ -452,20 +449,10 @@ template <> struct DenseMapInfo { }; /// \} -namespace yaml { -template <> struct ScalarTraits { - static void output(const lldb_private::ConstString &, void *, raw_ostream &); - static StringRef input(StringRef, void *, lldb_private::ConstString &); - static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } -}; -} // namespace yaml - inline raw_ostream &operator<<(raw_ostream &os, lldb_private::ConstString s) { os << s.GetStringRef(); return os; } } // namespace llvm -LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ConstString) - #endif // LLDB_UTILITY_CONSTSTRING_H diff --git a/gnu/llvm/lldb/include/lldb/Utility/DataBuffer.h b/gnu/llvm/lldb/include/lldb/Utility/DataBuffer.h index c778299b89a..e1c66fae745 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/DataBuffer.h +++ b/gnu/llvm/lldb/include/lldb/Utility/DataBuffer.h @@ -20,12 +20,12 @@ namespace lldb_private { /// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h" -/// A pure virtual protocol class for abstracted data buffers. +/// A pure virtual protocol class for abstracted read only data buffers. /// -/// DataBuffer is an abstract class that gets packaged into a shared pointer -/// that can use to implement various ways to store data (on the heap, memory -/// mapped, cached inferior memory). It gets used by DataExtractor so many -/// DataExtractor objects can share the same data and sub-ranges of that +/// DataBuffer is an abstract class that gets packaged into a shared +/// pointer that can use to implement various ways to store data (on the heap, +/// memory mapped, cached inferior memory). It gets used by DataExtractor so +/// many DataExtractor objects can share the same data and sub-ranges of that /// shared data, and the last object that contains a reference to the shared /// data will free it. /// @@ -42,52 +42,106 @@ namespace lldb_private { /// with some extra function calls to load the data before it gets accessed. class DataBuffer { public: - /// Destructor - /// - /// The destructor is virtual as other classes will inherit from this class - /// and be downcast to the DataBuffer pure virtual interface. The virtual - /// destructor ensures that destructing the base class will destruct the - /// class that inherited from it correctly. virtual ~DataBuffer() = default; - /// Get a pointer to the data. + /// Get the number of bytes in the data buffer. /// /// \return - /// A pointer to the bytes owned by this object, or NULL if the - /// object contains no bytes. - virtual uint8_t *GetBytes() = 0; + /// The number of bytes this object currently contains. + virtual lldb::offset_t GetByteSize() const = 0; /// Get a const pointer to the data. /// /// \return /// A const pointer to the bytes owned by this object, or NULL /// if the object contains no bytes. - virtual const uint8_t *GetBytes() const = 0; - - /// Get the number of bytes in the data buffer. - /// - /// \return - /// The number of bytes this object currently contains. - virtual lldb::offset_t GetByteSize() const = 0; + const uint8_t *GetBytes() const { return GetBytesImpl(); } llvm::ArrayRef GetData() const { return llvm::ArrayRef(GetBytes(), GetByteSize()); } + /// LLVM RTTI support. + /// { + static char ID; + virtual bool isA(const void *ClassID) const { return ClassID == &ID; } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } + +protected: + /// Get a const pointer to the data. + /// + /// \return + /// A const pointer to the bytes owned by this object, or NULL + /// if the object contains no bytes. + virtual const uint8_t *GetBytesImpl() const = 0; +}; + +/// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h" +/// A pure virtual protocol class for abstracted writable data buffers. +/// +/// DataBuffer is an abstract class that gets packaged into a shared pointer +/// that can use to implement various ways to store data (on the heap, memory +/// mapped, cached inferior memory). It gets used by DataExtractor so many +/// DataExtractor objects can share the same data and sub-ranges of that +/// shared data, and the last object that contains a reference to the shared +/// data will free it. +class WritableDataBuffer : public DataBuffer { +public: + /// Destructor + /// + /// The destructor is virtual as other classes will inherit from this class + /// and be downcast to the DataBuffer pure virtual interface. The virtual + /// destructor ensures that destructing the base class will destruct the + /// class that inherited from it correctly. + ~WritableDataBuffer() override = default; + + using DataBuffer::GetBytes; + using DataBuffer::GetData; + + /// Get a pointer to the data. + /// + /// \return + /// A pointer to the bytes owned by this object, or NULL if the + /// object contains no bytes. + uint8_t *GetBytes() { return const_cast(GetBytesImpl()); } + llvm::MutableArrayRef GetData() { return llvm::MutableArrayRef(GetBytes(), GetByteSize()); } + + /// LLVM RTTI support. + /// { + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || DataBuffer::isA(ClassID); + } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } }; -class DataBufferUnowned : public DataBuffer { +class DataBufferUnowned : public WritableDataBuffer { public: DataBufferUnowned(uint8_t *bytes, lldb::offset_t size) : m_bytes(bytes), m_size(size) {} - uint8_t *GetBytes() override { return m_bytes; } - const uint8_t *GetBytes() const override { return m_bytes; } + const uint8_t *GetBytesImpl() const override { return m_bytes; } lldb::offset_t GetByteSize() const override { return m_size; } + /// LLVM RTTI support. + /// { + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || WritableDataBuffer::isA(ClassID); + } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } private: uint8_t *m_bytes; lldb::offset_t m_size; diff --git a/gnu/llvm/lldb/include/lldb/Utility/DataBufferHeap.h b/gnu/llvm/lldb/include/lldb/Utility/DataBufferHeap.h index ace526bf0a4..a7270e95bf6 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/DataBufferHeap.h +++ b/gnu/llvm/lldb/include/lldb/Utility/DataBufferHeap.h @@ -27,7 +27,7 @@ namespace lldb_private { /// pages in. Large amounts of data that comes from files should probably use /// DataBufferLLVM, which can intelligently determine when memory mapping is /// optimal. -class DataBufferHeap : public DataBuffer { +class DataBufferHeap : public WritableDataBuffer { public: /// Default constructor /// @@ -54,17 +54,20 @@ public: /// The number of bytes in \a src to copy. DataBufferHeap(const void *src, lldb::offset_t src_len); + /// Construct by making a copy of a DataBuffer. + /// + /// \param[in] data_buffer + /// A read only data buffer to copy. + DataBufferHeap(const DataBuffer &data_buffer); + /// Destructor. /// /// Virtual destructor since this class inherits from a pure virtual base /// class #DataBuffer. ~DataBufferHeap() override; - /// \copydoc DataBuffer::GetBytes() - uint8_t *GetBytes() override; - /// \copydoc DataBuffer::GetBytes() const - const uint8_t *GetBytes() const override; + const uint8_t *GetBytesImpl() const override; /// \copydoc DataBuffer::GetByteSize() const lldb::offset_t GetByteSize() const override; @@ -80,8 +83,8 @@ public: /// to resize itself to. /// /// \return - /// The size in bytes after that this heap buffer was - /// successfully resized to. + /// The size in bytes after this heap buffer was resized. If + /// the resize failed the size will remain unchanged. lldb::offset_t SetByteSize(lldb::offset_t byte_size); /// Makes a copy of the \a src_len bytes in \a src. @@ -100,6 +103,17 @@ public: void Clear(); + /// LLVM RTTI support. + /// { + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || WritableDataBuffer::isA(ClassID); + } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } + private: // This object uses a std::vector to store its data. This takes care // of free the data when the object is deleted. diff --git a/gnu/llvm/lldb/include/lldb/Utility/DataBufferLLVM.h b/gnu/llvm/lldb/include/lldb/Utility/DataBufferLLVM.h index abb1bb40d53..1058d7ac081 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/DataBufferLLVM.h +++ b/gnu/llvm/lldb/include/lldb/Utility/DataBufferLLVM.h @@ -17,30 +17,65 @@ namespace llvm { class WritableMemoryBuffer; +class MemoryBuffer; class Twine; -} +} // namespace llvm namespace lldb_private { - class FileSystem; + class DataBufferLLVM : public DataBuffer { public: ~DataBufferLLVM() override; - uint8_t *GetBytes() override; - const uint8_t *GetBytes() const override; + const uint8_t *GetBytesImpl() const override; + lldb::offset_t GetByteSize() const override; + + /// LLVM RTTI support. + /// { + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || DataBuffer::isA(ClassID); + } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } + + /// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid + /// pointer. + explicit DataBufferLLVM(std::unique_ptr Buffer); + +protected: + std::unique_ptr Buffer; +}; + +class WritableDataBufferLLVM : public WritableDataBuffer { +public: + ~WritableDataBufferLLVM() override; + + const uint8_t *GetBytesImpl() const override; lldb::offset_t GetByteSize() const override; - char *GetChars() { return reinterpret_cast(GetBytes()); } + /// LLVM RTTI support. + /// { + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || WritableDataBuffer::isA(ClassID); + } + static bool classof(const DataBuffer *data_buffer) { + return data_buffer->isA(&ID); + } + /// } -private: - friend FileSystem; /// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid /// pointer. - explicit DataBufferLLVM(std::unique_ptr Buffer); + explicit WritableDataBufferLLVM( + std::unique_ptr Buffer); +protected: std::unique_ptr Buffer; }; -} +} // namespace lldb_private #endif diff --git a/gnu/llvm/lldb/include/lldb/Utility/DataEncoder.h b/gnu/llvm/lldb/include/lldb/Utility/DataEncoder.h index b944c09d5c4..7e1dec6992b 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/DataEncoder.h +++ b/gnu/llvm/lldb/include/lldb/Utility/DataEncoder.h @@ -16,6 +16,9 @@ #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + #include #include @@ -26,21 +29,34 @@ namespace lldb_private { /// An binary data encoding class. /// /// DataEncoder is a class that can encode binary data (swapping if needed) to -/// a data buffer. The data buffer can be caller owned, or can be shared data -/// that can be shared between multiple DataEncoder or DataEncoder instances. +/// a data buffer. The DataEncoder can be constructed with data that will be +/// copied into the internally owned buffer. This allows data to be modified +/// in the internal buffer. The DataEncoder object can also be constructed with +/// just a byte order and address size and data can be appended to the +/// internally owned buffer. +/// +/// Clients can get a shared pointer to the data buffer when done modifying or +/// creating the data to keep the data around after the lifetime of a +/// DataEncoder object. \see GetDataBuffer /// -/// \see DataBuffer +/// Client can get a reference to the object owned data as an array by calling +/// the GetData method. \see GetData class DataEncoder { public: /// Default constructor. /// - /// Initialize all members to a default empty state. + /// Initialize all members to a default empty state and create a empty memory + /// buffer that can be appended to. The ByteOrder and address size will be set + /// to match the current host system. DataEncoder(); - /// Construct with a buffer that is owned by the caller. + /// Construct an encoder that copies the specified data into the object owned + /// data buffer. /// - /// This constructor allows us to use data that is owned by the caller. The - /// data must stay around as long as this object is valid. + /// This constructor is designed to be used when you have a data buffer and + /// want to modify values within the buffer. A copy of the data will be made + /// in the internally owned buffer and that data can be fixed up and appended + /// to. /// /// \param[in] data /// A pointer to caller owned data. @@ -49,54 +65,37 @@ public: /// The length in bytes of \a data. /// /// \param[in] byte_order - /// A byte order of the data that we are extracting from. + /// A byte order for the data that will be encoded. /// /// \param[in] addr_size - /// A new address byte size value. - DataEncoder(void *data, uint32_t data_length, lldb::ByteOrder byte_order, - uint8_t addr_size); + /// A size of an address in bytes. \see PutAddress, AppendAddress + DataEncoder(const void *data, uint32_t data_length, + lldb::ByteOrder byte_order, uint8_t addr_size); - /// Construct with shared data. - /// - /// Copies the data shared pointer which adds a reference to the contained - /// in \a data_sp. The shared data reference is reference counted to ensure - /// the data lives as long as anyone still has a valid shared pointer to the - /// data in \a data_sp. + /// Construct an encoder that owns a heap based memory buffer. /// - /// \param[in] data_sp - /// A shared pointer to data. + /// This allows clients to create binary data from scratch by appending values + /// with the methods that start with "Append". /// /// \param[in] byte_order - /// A byte order of the data that we are extracting from. + /// A byte order for the data that will be encoded. /// /// \param[in] addr_size - /// A new address byte size value. - DataEncoder(const lldb::DataBufferSP &data_sp, lldb::ByteOrder byte_order, - uint8_t addr_size); + /// A size of an address in bytes. \see PutAddress, AppendAddress + DataEncoder(lldb::ByteOrder byte_order, uint8_t addr_size); - /// Destructor - /// - /// If this object contains a valid shared data reference, the reference - /// count on the data will be decremented, and if zero, the data will be - /// freed. ~DataEncoder(); - /// Clears the object state. - /// - /// Clears the object contents back to a default invalid state, and release - /// any references to shared data that this object may contain. - void Clear(); - /// Encode an unsigned integer of size \a byte_size to \a offset. /// /// Encode a single integer value at \a offset and return the offset that /// follows the newly encoded integer when the data is successfully encoded - /// into the existing data. There must be enough room in the data, else - /// UINT32_MAX will be returned to indicate that encoding failed. + /// into the existing data. There must be enough room in the existing data, + /// else UINT32_MAX will be returned to indicate that encoding failed. /// /// \param[in] offset - /// The offset within the contained data at which to put the - /// encoded integer. + /// The offset within the contained data at which to put the encoded + /// integer. /// /// \param[in] byte_size /// The size in byte of the integer to encode. @@ -111,6 +110,72 @@ public: /// was successfully encoded, UINT32_MAX if the encoding failed. uint32_t PutUnsigned(uint32_t offset, uint32_t byte_size, uint64_t value); + /// Encode an unsigned integer at offset \a offset. + /// + /// Encode a single unsigned integer value at \a offset and return the offset + /// that follows the newly encoded integer when the data is successfully + /// encoded into the existing data. There must be enough room in the data, + /// else UINT32_MAX will be returned to indicate that encoding failed. + /// + /// \param[in] offset + /// The offset within the contained data at which to put the encoded + /// integer. + /// + /// \param[in] value + /// The integer value to write. + /// + /// \return + /// The next offset in the bytes of this data if the integer was + /// successfully encoded, UINT32_MAX if the encoding failed. + uint32_t PutU8(uint32_t offset, uint8_t value); + uint32_t PutU16(uint32_t offset, uint16_t value); + uint32_t PutU32(uint32_t offset, uint32_t value); + uint32_t PutU64(uint32_t offset, uint64_t value); + + /// Append a unsigned integer to the end of the owned data. + /// + /// \param value + /// A unsigned integer value to append. + void AppendU8(uint8_t value); + void AppendU16(uint16_t value); + void AppendU32(uint32_t value); + void AppendU64(uint64_t value); + + /// Append an address sized integer to the end of the owned data. + /// + /// \param addr + /// A unsigned integer address value to append. The size of the address + /// will be determined by the address size specified in the constructor. + void AppendAddress(lldb::addr_t addr); + + /// Append a bytes to the end of the owned data. + /// + /// Append the bytes contained in the string reference. This function will + /// not append a NULL termination character for a C string. Use the + /// AppendCString function for this purpose. + /// + /// \param data + /// A string reference that contains bytes to append. + void AppendData(llvm::StringRef data); + + /// Append a bytes to the end of the owned data. + /// + /// Append the bytes contained in the array reference. + /// + /// \param data + /// A array reference that contains bytes to append. + void AppendData(llvm::ArrayRef data); + + /// Append a C string to the end of the owned data. + /// + /// Append the bytes contained in the string reference along with an extra + /// NULL termination character if the StringRef bytes doesn't include one as + /// the last byte. + /// + /// \param data + /// A string reference that contains bytes to append. + void AppendCString(llvm::StringRef data); + /// Encode an arbitrary number of bytes. /// /// \param[in] offset @@ -131,11 +196,10 @@ public: /// Encode an address in the existing buffer at \a offset bytes into the /// buffer. /// - /// Encode a single address (honoring the m_addr_size member) to the data - /// and return the next offset where subsequent data would go. pointed to by - /// \a offset_ptr. The size of the extracted address comes from the \a - /// m_addr_size member variable and should be set correctly prior to - /// extracting any address values. + /// Encode a single address to the data and return the next offset where + /// subsequent data would go. The size of the address comes from the \a + /// m_addr_size member variable and should be set correctly prior to encoding + /// any address values. /// /// \param[in] offset /// The offset where to encode the address. @@ -150,7 +214,10 @@ public: /// Put a C string to \a offset. /// - /// Encodes a C string into the existing data including the terminating + /// Encodes a C string into the existing data including the terminating. If + /// there is not enough room in the buffer to fit the entire C string and the + /// NULL terminator in the existing buffer bounds, then this function will + /// fail. /// /// \param[in] offset /// The offset where to encode the string. @@ -159,18 +226,43 @@ public: /// The string to encode. /// /// \return - /// 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. + /// The next valid offset within data if the put operation was successful, + /// else UINT32_MAX to indicate the put failed. uint32_t PutCString(uint32_t offset, const char *cstr); -private: - uint32_t PutU8(uint32_t offset, uint8_t value); - uint32_t PutU16(uint32_t offset, uint16_t value); - uint32_t PutU32(uint32_t offset, uint32_t value); - uint32_t PutU64(uint32_t offset, uint64_t value); + /// Get a shared copy of the heap based memory buffer owned by this object. + /// + /// This allows a data encoder to be used to create a data buffer that can + /// be extracted and used elsewhere after this object is destroyed. + /// + /// \return + /// A shared pointer to the DataBufferHeap that contains the data that was + /// encoded into this object. + std::shared_ptr GetDataBuffer() { + return m_data_sp; + } + + /// Get a access to the bytes that this references. + /// + /// This value will always return the data that this object references even if + /// the object was constructed with caller owned data. + /// + /// \return + /// A array reference to the data that this object references. + llvm::ArrayRef GetData() const; + + /// Get the number of bytes contained in this object. + /// + /// \return + /// The total number of bytes of data this object refers to. + size_t GetByteSize() const; + + lldb::ByteOrder GetByteOrder() const { return m_byte_order; } + + /// The address size to use when encoding pointers or addresses. + uint8_t GetAddressByteSize() const { return m_addr_size; } +private: uint32_t BytesLeft(uint32_t offset) const { const uint32_t size = GetByteSize(); if (size > offset) @@ -187,31 +279,6 @@ private: return length <= BytesLeft(offset); } - /// Adopt a subset of shared data in \a data_sp. - /// - /// Copies the data shared pointer which adds a reference to the contained - /// in \a data_sp. The shared data reference is reference counted to ensure - /// the data lives as long as anyone still has a valid shared pointer to the - /// data in \a data_sp. The byte order and address byte size settings remain - /// the same. If \a offset is not a valid offset in \a data_sp, then no - /// reference to the shared data will be added. If there are not \a length - /// bytes available in \a data starting at \a offset, the length will be - /// truncated to contains as many bytes as possible. - /// - /// \param[in] data_sp - /// A shared pointer to data. - /// - /// \param[in] offset - /// The offset into \a data_sp at which the subset starts. - /// - /// \param[in] length - /// The length in bytes of the subset of \a data_sp. - /// - /// \return - /// The number of bytes that this object now contains. - uint32_t SetData(const lldb::DataBufferSP &data_sp, uint32_t offset = 0, - uint32_t length = UINT32_MAX); - /// Test the validity of \a offset. /// /// \return @@ -219,28 +286,14 @@ private: /// object, \b false otherwise. bool ValidOffset(uint32_t offset) const { return offset < GetByteSize(); } - /// Get the number of bytes contained in this object. - /// - /// \return - /// The total number of bytes of data this object refers to. - size_t GetByteSize() const { return m_end - m_start; } - - /// A pointer to the first byte of data. - uint8_t *m_start = nullptr; - - /// A pointer to the byte that is past the end of the data. - uint8_t *m_end = nullptr; - - /// The byte order of the data we are extracting from. - lldb::ByteOrder m_byte_order; + /// The shared pointer to data that can grow as data is added + std::shared_ptr m_data_sp; - /// The address size to use when extracting pointers or - /// addresses - uint8_t m_addr_size; + /// The byte order of the data we are encoding to. + const lldb::ByteOrder m_byte_order; - /// The shared pointer to data that can - /// be shared among multiple instances - mutable lldb::DataBufferSP m_data_sp; + /// The address size to use when encoding pointers or addresses. + const uint8_t m_addr_size; DataEncoder(const DataEncoder &) = delete; const DataEncoder &operator=(const DataEncoder &) = delete; diff --git a/gnu/llvm/lldb/include/lldb/Utility/DataExtractor.h b/gnu/llvm/lldb/include/lldb/Utility/DataExtractor.h index 0923e5280cb..dbf0bce8c8d 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/DataExtractor.h +++ b/gnu/llvm/lldb/include/lldb/Utility/DataExtractor.h @@ -134,7 +134,12 @@ public: DataExtractor(const DataExtractor &data, lldb::offset_t offset, lldb::offset_t length, uint32_t target_byte_size = 1); - DataExtractor(const DataExtractor &rhs); + /// Copy constructor. + /// + /// The copy constructor is explicit as otherwise it is easy to make + /// unintended modification of a local copy instead of a caller's instance. + /// Also a needless copy of the \a m_data_sp shared pointer is/ expensive. + explicit DataExtractor(const DataExtractor &rhs); /// Assignment operator. /// @@ -149,6 +154,12 @@ public: /// A const reference to this object. const DataExtractor &operator=(const DataExtractor &rhs); + /// Move constructor and move assignment operators to complete the rule of 5. + /// + /// They would get deleted as we already defined those of rule of 3. + DataExtractor(DataExtractor &&rhs) = default; + DataExtractor &operator=(DataExtractor &&rhs) = default; + /// Destructor /// /// If this object contains a valid shared data reference, the reference @@ -1005,7 +1016,8 @@ protected: uint32_t m_addr_size; ///< The address size to use when extracting addresses. /// The shared pointer to data that can be shared among multiple instances lldb::DataBufferSP m_data_sp; - const uint32_t m_target_byte_size = 1; + /// Making it const would require implementation of move assignment operator. + uint32_t m_target_byte_size = 1; }; } // namespace lldb_private diff --git a/gnu/llvm/lldb/include/lldb/Utility/Diagnostics.h b/gnu/llvm/lldb/include/lldb/Utility/Diagnostics.h new file mode 100644 index 00000000000..5d23fa8ae23 --- /dev/null +++ b/gnu/llvm/lldb/include/lldb/Utility/Diagnostics.h @@ -0,0 +1,70 @@ +//===-- Diagnostics.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_DIAGNOSTICS_H +#define LLDB_UTILITY_DIAGNOSTICS_H + +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Error.h" + +#include +#include +#include +#include + +namespace lldb_private { + +/// Diagnostics are a collection of files to help investigate bugs and +/// troubleshoot issues. Any part of the debugger can register itself with the +/// help of a callback to emit one or more files into the diagnostic directory. +class Diagnostics { +public: + Diagnostics(); + ~Diagnostics(); + + /// Gather diagnostics in the given directory. + llvm::Error Create(const FileSpec &dir); + + /// Gather diagnostics and print a message to the given output stream. + /// @{ + bool Dump(llvm::raw_ostream &stream); + bool Dump(llvm::raw_ostream &stream, const FileSpec &dir); + /// @} + + void Report(llvm::StringRef message); + + using Callback = std::function; + + void AddCallback(Callback callback); + + static Diagnostics &Instance(); + + static bool Enabled(); + static void Initialize(); + static void Terminate(); + + /// Create a unique diagnostic directory. + static llvm::Expected CreateUniqueDirectory(); + +private: + static std::optional &InstanceImpl(); + + llvm::Error DumpDiangosticsLog(const FileSpec &dir) const; + + RotatingLogHandler m_log_handler; + + llvm::SmallVector m_callbacks; + std::mutex m_callbacks_mutex; +}; + +} // namespace lldb_private + +#endif diff --git a/gnu/llvm/lldb/include/lldb/Utility/Environment.h b/gnu/llvm/lldb/include/lldb/Utility/Environment.h index e2af2eb2463..27d740402c3 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/Environment.h +++ b/gnu/llvm/lldb/include/lldb/Utility/Environment.h @@ -56,8 +56,8 @@ public: using Base::try_emplace; using Base::operator[]; - Environment() : Base() {} - Environment(const Environment &RHS) : Base(RHS) {} + Environment() {} + Environment(const Environment &RHS) : Base(static_cast(RHS)) {} Environment(Environment &&RHS) : Base(std::move(RHS)) {} Environment(char *const *Env) : Environment(const_cast(Env)) {} @@ -73,7 +73,7 @@ public: return insert(std::make_pair(Split.first, std::string(Split.second))); } - void insert(const_iterator first, const_iterator last); + void insert(iterator first, iterator last); Envp getEnvp() const { return Envp(*this); } diff --git a/gnu/llvm/lldb/include/lldb/Utility/Event.h b/gnu/llvm/lldb/include/lldb/Utility/Event.h index 4e38f98a02f..8d2d94fe3fd 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/Event.h +++ b/gnu/llvm/lldb/include/lldb/Utility/Event.h @@ -42,7 +42,9 @@ public: virtual ~EventData(); virtual ConstString GetFlavor() const = 0; - + + virtual Log *GetLogChannel() { return nullptr; } + virtual void Dump(Stream *s) const; private: @@ -99,7 +101,7 @@ private: class EventDataReceipt : public EventData { public: - EventDataReceipt() : EventData(), m_predicate(false) {} + EventDataReceipt() : m_predicate(false) {} ~EventDataReceipt() override = default; @@ -110,7 +112,7 @@ public: ConstString GetFlavor() const override { return GetFlavorString(); } - bool WaitForEventReceived(const Timeout &timeout = llvm::None) { + bool WaitForEventReceived(const Timeout &timeout = std::nullopt) { return m_predicate.WaitForValueEqualTo(true, timeout); } diff --git a/gnu/llvm/lldb/include/lldb/Utility/FileSpec.h b/gnu/llvm/lldb/include/lldb/Utility/FileSpec.h index 0f4e6505e43..e4d3d12979c 100644 --- a/gnu/llvm/lldb/include/lldb/Utility/FileSpec.h +++ b/gnu/llvm/lldb/include/lldb/Utility/FileSpec.h @@ -10,6 +10,7 @@ #define LLDB_UTILITY_FILESPEC_H #include +#include #include #include "lldb/Utility/ConstString.h" @@ -18,7 +19,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" -#include "llvm/Support/YAMLTraits.h" #include #include @@ -191,18 +191,18 @@ public: static bool Match(const FileSpec &pattern, const FileSpec &file); /// Attempt to guess path style for a given path string. It returns a style, - /// if it was able to make a reasonable guess, or None if it wasn't. The guess - /// will be correct if the input path was a valid absolute path on the system - /// which produced it. On other paths the result of this function is - /// unreliable (e.g. "c:\foo.txt" is a valid relative posix path). - static llvm::Optional